diff options
Diffstat (limited to 'kviewshell/plugins/djvu/libdjvu/DjVuPort.h')
-rw-r--r-- | kviewshell/plugins/djvu/libdjvu/DjVuPort.h | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/kviewshell/plugins/djvu/libdjvu/DjVuPort.h b/kviewshell/plugins/djvu/libdjvu/DjVuPort.h new file mode 100644 index 00000000..99c165fb --- /dev/null +++ b/kviewshell/plugins/djvu/libdjvu/DjVuPort.h @@ -0,0 +1,518 @@ +//C- -*- C++ -*- +//C- ------------------------------------------------------------------- +//C- DjVuLibre-3.5 +//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun. +//C- Copyright (c) 2001 AT&T +//C- +//C- This software is subject to, and may be distributed under, the +//C- GNU General Public License, Version 2. The license should have +//C- accompanied the software or you may obtain a copy of the license +//C- from the Free Software Foundation at http://www.fsf.org . +//C- +//C- This program is distributed in the hope that it will be useful, +//C- but WITHOUT ANY WARRANTY; without even the implied warranty of +//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//C- GNU General Public License for more details. +//C- +//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library +//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech +//C- Software authorized us to replace the original DjVu(r) Reference +//C- Library notice by the following text (see doc/lizard2002.djvu): +//C- +//C- ------------------------------------------------------------------ +//C- | DjVu (r) Reference Library (v. 3.5) +//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved. +//C- | The DjVu Reference Library is protected by U.S. Pat. No. +//C- | 6,058,214 and patents pending. +//C- | +//C- | This software is subject to, and may be distributed under, the +//C- | GNU General Public License, Version 2. The license should have +//C- | accompanied the software or you may obtain a copy of the license +//C- | from the Free Software Foundation at http://www.fsf.org . +//C- | +//C- | The computer code originally released by LizardTech under this +//C- | license and unmodified by other parties is deemed "the LIZARDTECH +//C- | ORIGINAL CODE." Subject to any third party intellectual property +//C- | claims, LizardTech grants recipient a worldwide, royalty-free, +//C- | non-exclusive license to make, use, sell, or otherwise dispose of +//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the +//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU +//C- | General Public License. This grant only confers the right to +//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to +//C- | the extent such infringement is reasonably necessary to enable +//C- | recipient to make, have made, practice, sell, or otherwise dispose +//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to +//C- | any greater extent that may be necessary to utilize further +//C- | modifications or combinations. +//C- | +//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY +//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF +//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//C- +------------------------------------------------------------------ +// +// $Id: DjVuPort.h,v 1.8 2003/11/07 22:08:21 leonb Exp $ +// $Name: release_3_5_15 $ + +#ifndef _DJVUPORT_H +#define _DJVUPORT_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#if NEED_GNUG_PRAGMAS +# pragma interface +#endif + + +#include "GThreads.h" +#include "GURL.h" + +#ifdef HAVE_NAMESPACES +namespace DJVU { +# ifdef NOT_DEFINED // Just to fool emacs c++ mode +} +#endif +#endif + +class DataPool; + +/** @name DjVuPort.h + Files #"DjVuPort.h"# and #"DjVuPort.cpp"# implement a communication + mechanism between different parties involved in decoding DjVu files. + It should be pretty clear that the creator of \Ref{DjVuDocument} and + \Ref{DjVuFile} would like to receive some information about the progress + of decoding, errors occurred, etc. It may also want to provide source data + for decoders (like it's done in the plugin where the real data is downloaded + from the net and is fed into DjVu decoders). + + Normally this functionality is implemented by means of callbacks which are + run when a given condition comes true. Unfortunately it's not quite easy + to implement this strategy in our case. The reason is that there may be + more than one "client" working with the same document, and the document + should send the information to each of the clients. This could be done by + means of callback {\em lists}, of course, but we want to achieve more + bulletproof results: we want to be sure that the client that we're about + to contact is still alive, and is not being destroyed by another thread. + Besides, we are going to call these "callbacks" from many places, from + many different classes. Maintaining multi-thread safe callback lists is + very difficult. + + Finally, we want to provide some default implementation of these + "callbacks" in the library, which should attempt to process the requests + themselves if they can, and contact the client only if they're unable to + do it (like in the case of \Ref{DjVuPort::request_data}() with local URL + where \Ref{DjVuDocument} can get the data from the hard drive itself not + disturbing the document's creator. + + Two classes implement a general communication mechanism: \Ref{DjVuPort} and + \Ref{DjVuPortcaster}. Any sender and recipient of requests should be a + subclass of \Ref{DjVuPort}. \Ref{DjVuPortcaster} maintains a map of + routes between \Ref{DjVuPort}s, which should be configured by somebody + else. Whenever a port wants to send a request, it calls the corresponding + function of \Ref{DjVuPortcaster}, and the portcaster relays the request to + all the destinations that it sees in the internal map. + + The \Ref{DjVuPortcaster} is responsible for keeping the map up to date by + getting rid of destinations that have been destroyed. Map updates are + performed from a single place and are serialized by a global monitor. + + @memo DjVu decoder communication mechanism. + @author Andrei Erofeev <[email protected]>\\ + L\'eon Bottou <[email protected]> + @version #$Id: DjVuPort.h,v 1.8 2003/11/07 22:08:21 leonb Exp $# */ +//@{ + +class DjVuPort; +class DjVuPortcaster; +class DjVuFile; + +/** Base class for notification targets. + #DjVuPort# provides base functionality for classes willing to take part in + sending and receiving messages generated during decoding process. You + need to derive your class from #DjVuPort# if you want it to be able to + send or receive requests. In addition, for receiving requests you should + override one or more virtual function. + + {\bf Important remark} --- All ports should be allocated on the heap using + #operator new# and immediately secured using a \Ref{GP} smart pointer. + Ports which are not secured by a smart-pointer are not considered + ``alive'' and never receive notifications! */ + +class DjVuPort : public GPEnabled +{ +public: + DjVuPort(); + virtual ~DjVuPort(); + static void *operator new (size_t sz); + static void operator delete(void *addr); + + /** Use this function to get a copy of the global \Ref{DjVuPortcaster}. */ + static DjVuPortcaster *get_portcaster(void); + + /** Copy constructor. When #DjVuPort#s are copied, the portcaster + copies all incoming and outgoing routes of the original. */ + DjVuPort(const DjVuPort & port); + + /** Copy operator. Similarly to the copy constructor, the portcaster + copies all incoming and outgoing coming routes of the original. */ + DjVuPort & operator=(const DjVuPort & port); + + /** Should return 1 if the called class inherits class #class_name#. + When a destination receives a request, it can retrieve the pointer + to the source #DjVuPort#. This virtual function should be able + to help to identify the source of the request. For example, + \Ref{DjVuFile} is also derived from #DjVuPort#. In order for + the receiver to recognize the sender, the \Ref{DjVuFile} should + override this function to return #TRUE# when the #class_name# + is either #DjVuPort# or #DjVuFile# */ + virtual bool inherits(const GUTF8String &class_name) const; + + /** @name Notifications. + These virtual functions may be overridden by the subclasses + of #DjVuPort#. They are called by the \Ref{DjVuPortcaster} + when the port is alive and when there is a route between the + source of the notification and this port. */ + //@{ + + /** This request is issued to request translation of the ID, used + in an DjVu INCL chunk to a URL, which may be used to request + data associated with included file. \Ref{DjVuDocument} usually + intercepts all such requests, and the user doesn't have to + worry about the translation */ + virtual GURL id_to_url(const DjVuPort * source, const GUTF8String &id); + + /** This request is used to get a file corresponding to the + given ID. \Ref{DjVuDocument} is supposed to intercept it + and either create a new instance of \Ref{DjVuFile} or reuse + an existing one from the cache. */ + virtual GP<DjVuFile> id_to_file(const DjVuPort * source, const GUTF8String &id); + + /** This request is issued when decoder needs additional data + for decoding. Both \Ref{DjVuFile} and \Ref{DjVuDocument} are + initialized with a URL, not the document data. As soon as + they need the data, they call this function, whose responsibility + is to locate the source of the data basing on the #URL# passed + and return it back in the form of the \Ref{DataPool}. If this + particular receiver is unable to fullfil the request, it should + return #0#. */ + virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url); + + /** This notification is sent when an error occurs and the error message + should be shown to the user. The receiver should return #0# if it is + unable to process the request. Otherwise the receiver should return 1. */ + virtual bool notify_error(const DjVuPort * source, const GUTF8String &msg); + + /** This notification is sent to update the decoding status. The + receiver should return #0# if it is unable to process the + request. Otherwise the receiver should return 1. */ + virtual bool notify_status(const DjVuPort * source, const GUTF8String &msg); + + /** This notification is sent by \Ref{DjVuImage} when it should be + redrawn. It may be used to implement progressive redisplay. + + @param source The sender of the request */ + virtual void notify_redisplay(const class DjVuImage * source); + + /** This notification is sent by \ref{DjVuImage} when its geometry + has been changed as a result of decoding. It may be used to + implement progressive redisplay. */ + virtual void notify_relayout(const class DjVuImage * source); + + /** This notification is sent when a new chunk has been decoded. */ + virtual void notify_chunk_done(const DjVuPort * source, const GUTF8String &name); + + /** This notification is sent after the \Ref{DjVuFile} flags have + been changed. This happens, for example, when: + \begin{itemize} + \item Decoding succeeded, failed or just stopped + \item All data has been received + \item All included files have been created + \end{itemize} + + @param source \Ref{DjVuFile}, which flags have been changed + @param set_mask bits, which have been set + @param clr_mask bits, which have been cleared */ + virtual void notify_file_flags_changed(const class DjVuFile * source, + long set_mask, long clr_mask); + + /** This notification is sent after the \Ref{DjVuDocument} flags have + been changed. This happens, for example, after it receives enough + data and can determine its structure (#BUNDLED#, #OLD_INDEXED#, etc.). + + @param source \Ref{DjVuDocument}, which flags have been changed + @param set_mask bits, which have been set + @param clr_mask bits, which have been cleared */ + virtual void notify_doc_flags_changed(const class DjVuDocument * source, + long set_mask, long clr_mask); + + /** This notification is sent from time to time while decoding is in + progress. The purpose is obvious: to provide a way to know how much + is done and how long the decoding will continue. Argument #done# is + a number from 0 to 1 reflecting the progress. */ + virtual void notify_decode_progress(const DjVuPort * source, float done); + + /** This is the standard types for defining what to do in case of errors. + This is only used by some of the subclasses, but it needs to be + defined here to guarantee all subclasses use the same enum types. + In general, many errors are non recoverable. Using a setting + other than ABORT may just result in even more errors. */ + enum ErrorRecoveryAction {ABORT=0,SKIP_PAGES=1,SKIP_CHUNKS=2,KEEP_ALL=3 }; + //@} +public: + class DjVuPortCorpse; +private: + static GCriticalSection * corpse_lock; + static DjVuPortCorpse * corpse_head, * corpse_tail; + static int corpse_num; +}; + +/** Simple port. + An instance of #DjVuSimplePort# is automatically created when you create a + \Ref{DjVuFile} or a \Ref{DjVuDocument} without specifying a port. This + simple port can retrieve data for local urls (i.e. urls referring to local + files) and display error messages on #stderr#. All other notifications + are ignored. */ + +class DjVuSimplePort : public DjVuPort +{ +public: + /// Returns 1 if #class_name# is #"DjVuPort"# or #"DjVuSimplePort"#. + virtual bool inherits(const GUTF8String &class_name) const; + + /** If #url# is local, it created a \Ref{DataPool}, connects it to the + file with the given name and returns. Otherwise returns #0#. */ + virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url); + + /// Displays error on #stderr#. Always returns 1. + virtual bool notify_error(const DjVuPort * source, const GUTF8String &msg); + + /// Displays status on #stderr#. Always returns 1. + virtual bool notify_status(const DjVuPort * source, const GUTF8String &msg); +}; + + +/** Memory based port. + This \Ref{DjVuPort} maintains a map associating pseudo urls with data + segments. It processes the #request_data# notifications according to this + map. After initializing the port, you should add as many pairs #<url, + pool># as needed need and add a route from a \Ref{DjVuDocument} or + \Ref{DjVuFile} to this port. */ + +class DjVuMemoryPort : public DjVuPort +{ +public: + /// Returns 1 if #class_name# is #"DjVuPort"# or #"DjVuMemoryPort"# + virtual bool inherits(const GUTF8String &class_name) const; + + /** If #url# is one of those, that have been added before by means + of \Ref{add_data}() function, it will return the associated + \Ref{DataPool}. #ZERO# otherwize. */ + virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url); + + /** Adds #<url, pool># pair to the internal map. From now on, if + somebody asks for data corresponding to the #url#, it will + be returning the #pool# */ + void add_data(const GURL & url, const GP<DataPool> & pool); +private: + GCriticalSection lock; + GPMap<GURL, DataPool>map; +}; + + + +/** Maintains associations between ports. + It monitors the status of all ports (have they been destructed yet?), + accepts requests and notifications from them and forwards them to + destinations according to internally maintained map of routes. + + The caller can modify the route map any way he likes (see + \Ref{add_route}(), \Ref{del_route}(), \Ref{copy_routes}(), + etc. functions). Any port can be either a sender of a message, an + intermediary receiver or a final destination. + + When a request is sent, the #DjVuPortcaster# computes the list of + destinations by consulting with the route map. Notifications are only + sent to ``alive'' ports. A port is alive if it is referenced by a valid + \Ref{GP} smartpointer. As a consequence, a port usually becomes alive + after running the constructor (since the returned pointer is then assigned + to a smartpointer) and is no longer alive when the port is destroyed + (because it would not be destroyed if a smartpointer was referencing it). + + Destination ports are sorted according to their distance from the source. + For example, if port {\bf A} is connected to ports {\bf B} and {\bf C} + directly, and port {\bf B} is connected to {\bf D}, then {\bf B} and {\bf + C} are assumed to be one hop away from {\bf A}, while {\bf D} is two hops + away from {\bf A}. + + In some cases the requests and notifications are sent to every possible + destination, and the order is not significant (like it is for + \Ref{notify_file_flags_changed}() request). Others should be sent to the closest + destinations first, and only then to the farthest, in case if they have + not been processed by the closest. The examples are \Ref{request_data}(), + \Ref{notify_error}() and \Ref{notify_status}(). + + The user is not expected to create the #DjVuPortcaster# itself. He should + use \Ref{get_portcaster}() global function instead. */ +class DjVuPortcaster +{ +public: + /** Use this function to get a copy of the global \Ref{DjVuPortcaster}. */ + static DjVuPortcaster *get_portcaster(void) + { return DjVuPort::get_portcaster(); } ; + + /** The default constructor. */ + DjVuPortcaster(void); + + virtual ~DjVuPortcaster(void); + + /** Removes the specified port from all routes. It will no longer + be able to receive or generate messages and will be considered + {\bf "dead"} by \Ref{is_port_alive}() function. */ + void del_port(const DjVuPort * port); + + /** Adds route from #src# to #dst#. Whenever a request is + sent or received by #src#, it will be forwarded to #dst# as well. + @param src The source + @param dst The destination */ + void add_route(const DjVuPort *src, DjVuPort *dst); + + /** The opposite of \Ref{add_route}(). Removes the association + between #src# and #dst# */ + void del_route(const DjVuPort *src, DjVuPort *dst); + + /** Copies all incoming and outgoing routes from #src# to + #dst#. This function should be called when a \Ref{DjVuPort} is + copied, if you want to preserve the connectivity. */ + void copy_routes(DjVuPort *dst, const DjVuPort *src); + + /** Returns a smart pointer to the port if #port# is a valid pointer + to an existing #DjVuPort#. Returns a null pointer otherwise. */ + GP<DjVuPort> is_port_alive(DjVuPort *port); + + /** Assigns one more {\em alias} for the specified \Ref{DjVuPort}. + {\em Aliases} are names, which can be used later to retrieve this + \Ref{DjVuPort}, if it still exists. Any \Ref{DjVuPort} may have + more than one {\em alias}. But every {\em alias} must correspond + to only one \Ref{DjVuPort}. Thus, if the specified alias is + already associated with another port, this association will be + removed. */ + void add_alias(const DjVuPort * port, const GUTF8String &alias); + + /** Removes all the aliases */ + static void clear_all_aliases(void); + + /** Removes all aliases associated with the given \Ref{DjVuPort}. */ + void clear_aliases(const DjVuPort * port); + + /** Returns \Ref{DjVuPort} associated with the given #alias#. If nothing + is known about name #alias#, or the port associated with it has + already been destroyed #ZERO# pointer will be returned. */ + GP<DjVuPort> alias_to_port(const GUTF8String &name); + + /** Returns a list of \Ref{DjVuPort}s with aliases starting with + #prefix#. If no \Ref{DjVuPort}s have been found, empty + list is returned. */ + GPList<DjVuPort> prefix_to_ports(const GUTF8String &prefix); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest until one of them returns non-empty \Ref{GURL}. */ + virtual GURL id_to_url(const DjVuPort * source, const GUTF8String &id); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest until one of them returns non-zero pointer to + \Ref{DjVuFile}. */ + virtual GP<DjVuFile> id_to_file(const DjVuPort * source, const GUTF8String &id); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest until one of them returns non-zero \Ref{DataPool}. */ + virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url); + + /** Computes destination list for #source# and calls the corresponding. + function in each of the ports from the destination starting from + the closest until one of them returns 1. */ + virtual bool notify_error(const DjVuPort * source, const GUTF8String &msg); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest until one of them returns 1. */ + virtual bool notify_status(const DjVuPort * source, const GUTF8String &msg); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_redisplay(const class DjVuImage * source); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_relayout(const class DjVuImage * source); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_chunk_done(const DjVuPort * source, const GUTF8String &name); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_file_flags_changed(const class DjVuFile * source, + long set_mask, long clr_mask); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_doc_flags_changed(const class DjVuDocument * source, + long set_mask, long clr_mask); + + /** Computes destination list for #source# and calls the corresponding + function in each of the ports from the destination list starting from + the closest. */ + virtual void notify_decode_progress(const DjVuPort * source, float done); + +private: + // We use these 'void *' to minimize template instantiations. + friend class DjVuPort; + GCriticalSection map_lock; + GMap<const void *, void *> route_map; // GMap<DjVuPort *, GList<DjVuPort *> *> + GMap<const void *, void *> cont_map; // GMap<DjVuPort *, DjVuPort *> + GMap<GUTF8String, const void *> a2p_map; // GMap<GUTF8String, DjVuPort *> + void add_to_closure(GMap<const void*, void*> & set, + const DjVuPort *dst, int distance); + void compute_closure(const DjVuPort *src, GPList<DjVuPort> &list, + bool sorted=false); +}; + + +inline bool +DjVuPort::inherits(const GUTF8String &class_name) const +{ + return (class_name == "DjVuPort"); +} + +inline bool +DjVuSimplePort::inherits(const GUTF8String &class_name) const +{ + return + (class_name == "DjVuSimplePort") || DjVuPort::inherits(class_name); +} + +inline bool +DjVuMemoryPort::inherits(const GUTF8String &class_name) const +{ + return + (class_name == "DjVuMemoryPort") || DjVuPort::inherits(class_name); +} + +//@} + + +#ifdef HAVE_NAMESPACES +} +# ifndef NOT_USING_DJVU_NAMESPACE +using namespace DJVU; +# endif +#endif +#endif |