source: trunk/libdjvu/DataPool.h @ 269

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

DJVU plugin: djvulibre updated to version 3.5.19

File size: 26.1 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: DataPool.h,v 1.12 2007/03/25 20:48:29 leonb Exp $
57// $Name: release_3_5_19 $
58
59#ifndef _DATAPOOL_H
60#define _DATAPOOL_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 "GString.h"
71#include "GURL.h"
72
73#ifdef HAVE_NAMESPACES
74namespace DJVU {
75# ifdef NOT_DEFINED // Just to fool emacs c++ mode
76}
77#endif
78#endif
79
80class ByteStream;
81
82/** @name DataPool.h
83    Files #"DataPool.h"# and #"DataPool.cpp"# implement classes \Ref{DataPool}
84    and \Ref{DataRange} used by DjVu decoder to access data.
85
86    The main goal of class \Ref{DataPool} is to provide concurrent access
87    to the same data from many threads with a possibility to add data
88    from yet another thread. It is especially important in the case of the
89    Netscape plugin when data is not immediately available, but decoding
90    should be started as soon as possible. In this situation it is vital
91    to provide transparent access to the data from many threads possibly
92    blocking readers that try to access information that has not been
93    received yet.
94
95    When the data is local though, it can be accessed directly using
96    standard IO mechanism. To provide a uniform interface for decoding
97    routines, \Ref{DataPool} supports file mode as well.
98
99    @memo Thread safe data storage
100    @author Andrei Erofeev <eaf@geocities.com>
101    @version #$Id: DataPool.h,v 1.12 2007/03/25 20:48:29 leonb Exp $#
102*/
103
104//@{
105
106/** Thread safe data storage.
107    The purpose of #DataPool# is to provide a uniform interface for
108    accessing data from decoding routines running in a multi-threaded
109    environment. Depending on the mode of operation it may contain the
110    actual data, may be connected to another #DataPool# or may be mapped
111    to a file. Regardless of the mode, the class returns data in a
112    thread-safe way, blocking reading threads if there is no data of
113    interest available. This blocking is especially useful in the
114    networking environment (plugin) when there is a running decoding thread,
115    which wants to start decoding as soon as there is just one byte available
116    blocking if necessary.
117
118    Access to data in a #DataPool# may be direct (Using \Ref{get_data}()
119    function) or sequential (See \Ref{get_stream}() function).
120
121    If the #DataPool# is not connected to anything, that is it contains
122    some real data, this data can be added to it by means of two
123    \Ref{add_data}() functions. One of them adds data sequentially maintaining
124    the offset of the last block of data added by it. The other can store
125    data anywhere. Thus it's important to realize, that there may be "white
126    spots" in the data storage.
127
128    There is also a way to test if data is available for some given data
129    range (See \Ref{has_data}()). In addition to this mechanism, there are
130    so-called {\em trigger callbacks}, which are called, when there is
131    all data available for a given data range.
132
133    Let us consider all modes of operation in details:
134
135    \begin{enumerate}
136       \item {\bf Not connected #DataPool#}. In this mode the #DataPool#
137             contains some real data. As mentioned above, it may be added 
138             by means of two functions \Ref{add_data}() operating independent
139             of each other and allowing to add data sequentially and
140             directly to any place of data storage. It's important to call
141             function \Ref{set_eof}() after all data has been added.
142
143             Functions like \Ref{get_data}() or \Ref{get_stream}() can
144             be used to obtain direct or sequential access to the data. As
145             long as \Ref{is_eof}() is #FALSE#, #DataPool# will block every
146             reader, which is trying to read unavailable data until it
147             really becomes available. But as soon as \Ref{is_eof}() is
148             #TRUE#, any attempt to read non-existing data will read #0# bytes.
149
150             Taking into account the fact, that #DataPool# was designed to
151             store DjVu files, which are in IFF formats, it becomes possible
152             to predict the size of the #DataPool# as soon as the first
153             #32# bytes have been added. This is invaluable for estimating
154             download progress. See function \Ref{get_length}() for details.
155             If this estimate fails (which means, that stored data is not
156             in IFF format), \Ref{get_length}() returns #-1#.
157
158             Triggers may be added and removed by means of \Ref{add_trigger}()
159             and \Ref{del_trigger}() functions. \Ref{add_trigger}() takes
160             a data range. As soon as all data in that data range is
161             available, the trigger callback will be called.
162
163             All trigger callbacks will be called when #EOF# condition
164             has been set.
165
166       \item {\bf #DataPool# connected to another #DataPool#}. In this
167             {\em slave} mode you can map a given #DataPool# to any offsets
168             range inside another #DataPool#. You can connect the slave
169             #DataPool# even if there is no data in the master #DataPool#.
170             Any \Ref{get_data}() request will be forwarded to the master
171             #DataPool#, and it will be responsible for blocking readers
172             trying to access unavailable data.
173
174             The usage of \Ref{add_data}() functions is prohibited for
175             connected #DataPool#s.
176
177             The offsets range used to map a slave #DataPool# can be fully
178             specified (both start offset and length are positive numbers)
179             or partially specified (the length is negative). In this mode
180             the slave #DataPool# is assumed to extend up to the end
181             of the master #DataPool#.
182
183             Triggers may be used with slave #DataPool#s as well as with
184             the master ones.
185
186             Calling \Ref{stop}() function of a slave will stop only the slave
187             (and any other slave connected to it), but not the master.
188
189             \Ref{set_eof}() function is meaningless for slaves. They obtain
190             the #ByteStream::EndOfFile# status from their master.
191
192             Depending on the offsets range passed to the constructor,
193             \Ref{get_length}() returns different values. If the length
194             passed to the constructor was positive, then it is returned
195             by \Ref{get_length}() all the time. Otherwise the value returned
196             is either #-1# if master's length is still unknown (it didn't
197             manage to parse IFF data yet) or it is calculated as
198             #masters_length-slave_start#.
199
200       \item {\bf #DataPool# connected to a file}. This mode is quite similar
201             to the case, when the #DataPool# is connected to another
202             #DataPool#. Similarly, the #DataPool# stores no data inside.
203             It just forwards all \Ref{get_data}() requests to the underlying
204             source (a file in this case). Thus these requests will never
205             block the reader. But they may return #0# if there is no data
206             available at the requested offset.
207
208             The usage of \Ref{add_data}() functions is meaningless and
209             is prohibited.
210
211             \Ref{is_eof}() function always returns #TRUE#. Thus \Ref{set_eof}()
212             us meaningless and does nothing.
213
214             \Ref{get_length}() function always returns the file size.
215
216             Calling \Ref{stop}() function will stop this #DataPool# and
217             any other slave connected to it.
218
219             Trigger callbacks passed through \Ref{add_trigger}() function
220             are called immediately.
221
222             This mode is useful to read and decode DjVu files without reading
223             and storing them in full in memory.
224    \end{enumerate}
225*/
226
227class DataPool : public GPEnabled
228{
229public: // Classes used internally by DataPool
230        // These are declared public to support buggy C++ compilers.
231   class Incrementor;
232   class Reader;
233   class Trigger;
234   class OpenFiles;
235   class OpenFiles_File;
236   class BlockList;
237   class Counter;
238protected:
239   DataPool(void);
240
241public:
242      /** @name Initialization */
243      //@{
244      /** Default creator. Will prepare #DataPool# for accepting data
245          added through functions \Ref{add_data}(). Use \Ref{connect}()
246          functions if you want to map this #DataPool# to another or
247          to a file. */
248   static GP<DataPool> create(void);
249
250      /** Creates and initialized the #DataPool# with data from stream #str#.
251          The constructor will read the stream's contents and add them
252          to the pool using the \Ref{add_data}() function. Afterwards it
253          will call \Ref{set_eof}() function, and no other data will be
254          allowed to be added to the pool. */
255   static GP<DataPool> create(const GP<ByteStream> & str);
256
257      /** Initializes the #DataPool# in slave mode and connects it
258          to the specified offsets range of the specified master #DataPool#.
259          It is equivalent to calling default constructor and function
260          \Ref{connect}().
261
262          @param master_pool Master #DataPool# providing data for this slave
263          @param start Beginning of the offsets range which the slave is
264                 mapped into
265          @param length Length of the offsets range. If negative, the range
266                 is assumed to extend up to the end of the master #DataPool#.
267      */
268   static GP<DataPool> create(const GP<DataPool> & master_pool, int start=0, int length=-1);
269
270      /** Initializes the #DataPool# in slave mode and connects it
271          to the specified offsets range of the specified file.
272          It is equivalent to calling default constructor and function
273          \Ref{connect}().
274          @param url Name of the file to connect to.
275          @param start Beginning of the offsets range which the #DataPool# is
276                 mapped into
277          @param length Length of the offsets range. If negative, the range
278                 is assumed to extend up to the end of the file.
279      */
280   static GP<DataPool> create(const GURL &url, int start=0, int length=-1);
281
282   virtual ~DataPool();
283
284      /** Switches the #DataPool# to slave mode and connects it to the
285          specified offsets range of the master #DataPool#.
286          @param master_pool Master #DataPool# providing data for this slave
287          @param start Beginning of the offsets range which the slave is
288                 mapped into
289          @param length Length of the offsets range. If negative, the range
290                 is assumed to extend up to the end of the master #DataPool#.
291      */
292   void         connect(const GP<DataPool> & master_pool, int start=0, int length=-1);
293      /** Connects the #DataPool# to the specified offsets range of
294          the named #url#.
295          @param url Name of the file to connect to.
296          @param start Beginning of the offsets range which the #DataPool# is
297                 mapped into
298          @param length Length of the offsets range. If negative, the range
299                 is assumed to extend up to the end of the file.
300      */
301   void         connect(const GURL &url, int start=0, int length=-1);
302      //@}
303
304      /** Tells the #DataPool# to stop serving readers.
305
306          If #only_blocked# flag is #TRUE# then only those requests will
307          be processed, which would not block. Any attempt to get non-existing
308          data would result in a #STOP# exception (instead of blocking until
309          data is available).
310
311          If #only_blocked# flag is #FALSE# then any further attempt to read
312          from this #DataPool# (as well as from any #DataPool# connected
313          to this one) will result in a #STOP# exception. */
314   void         stop(bool only_blocked=false);
315
316      /** @name Adding data.
317          Please note, that these functions are for not connected #DataPool#s
318          only. You can not add data to a #DataPool#, which is connected
319          to another #DataPool# or to a file.
320        */
321      //@{
322      /** Appends the new block of data to the #DataPool#. There are two
323          \Ref{add_data}() functions available. One is for adding data
324          sequentially. It keeps track of the last byte position, which has
325          been stored {\bf by it} and always appends the next block after
326          this position. The other \Ref{add_data}() can store data anywhere.
327         
328          The function will unblock readers waiting for data if this data
329          arrives with this block. It may also trigger some {\em trigger
330          callbacks}, which may have been added by means of \Ref{add_trigger}()
331          function.
332
333          {\bf Note:} After all the data has been added, it's necessary
334          to call \Ref{set_eof}() to tell the #DataPool# that nothing else
335          is expected.
336
337          {\bf Note:} This function may not be called if the #DataPool#
338          has been connected to something.
339
340          @param buffer data to append
341          @param size length of the {\em buffer}
342      */
343   void         add_data(const void * buffer, int size);
344
345      /** Stores the specified block of data at the specified offset.
346          Like the function above this one can also unblock readers
347          waiting for data and engage trigger callbacks. The difference
348          is that {\bf this} function can store data anywhere.
349
350          {\bf Note:} After all the data has been added, it's necessary
351          to call \Ref{set_eof}() to tell the #DataPool# that nothing else
352          is expected.
353
354          {\bf Note:} This function may not be called if the #DataPool#
355          has been connected to something.
356
357          @param buffer data to store
358          @param offset where to store the data
359          @param size length of the {\em buffer} */
360   void         add_data(const void * buffer, int offset, int size);
361
362      /** Tells the #DataPool# that all data has been added and nothing else
363          is anticipated. When #EOF# is true, any reader attempting to read
364          non existing data will not be blocked. It will either read #ZERO#
365          bytes or will get an #ByteStream::EndOfFile# exception (see \Ref{get_data}()).
366          Calling this function will also activate all registered trigger
367          callbacks.
368
369          {\bf Note:} This function is meaningless and does nothing
370          when the #DataPool# is connected to another #DataPool# or to
371          a file. */
372   void         set_eof(void);
373      //@}
374
375      /** @name Accessing data.
376          These functions provide direct and sequential access to the
377          data of the #DataPool#. If the #DataPool# is not connected
378          (contains some real data) then it handles the requests itself.
379          Otherwise they are forwarded to the master #DataPool# or the file.
380        */
381      //@{
382      /** Attempts to return a block of data at the given #offset#
383          of the given #size#.
384
385          \begin{enumerate}
386             \item If the #DataPool# is connected to another #DataPool# or
387                   to a file, the request will just be forwarded to them.
388             \item If the #DataPool# is not connected to anything and
389                   some of the data requested is in the internal buffer,
390                   the function copies available data to #buffer# and returns
391                   immediately.
392
393                   If there is no data available, and \Ref{is_eof}() returns
394                   #FALSE#, the reader (and the thread) will be {\bf blocked}
395                   until the data actually arrives. Please note, that since
396                   the reader is blocked, it should run in a separate thread
397                   so that other threads have a chance to call \Ref{add_data}().
398                   If there is no data available, but \Ref{is_eof}() is #TRUE#
399                   the behavior is different and depends on the #DataPool#'s
400                   estimate of the file size:
401                   \begin{itemize}
402                      \item If #DataPool# learns from the IFF structure of the
403                            data, that its size should be greater than it
404                            really is, then any attempt to read non-existing
405                            data in the range of {\em valid} offsets will
406                            result in an #ByteStream::EndOfFile# exception. This is done to
407                            indicate, that there was an error in adding data,
408                            and the data requested is {\bf supposed} to be
409                            there, but has actually not been added.
410                      \item If #DataPool#'s expectations about the data size
411                            coincide with the reality then any attempt to
412                            read data beyond the legal range of offsets will
413                            result in #ZERO# bytes returned.
414                   \end{itemize}.
415          \end{enumerate}.
416
417          @param buffer Buffer to be filled with data
418          @param offset Offset in the #DataPool# to read data at
419          @param size Size of the {\em buffer}
420          @return The number of bytes actually read
421          @exception STOP The stream has been stopped
422          @exception EOF The requested data is not there and will not be added,
423                     although it should have been.
424      */
425   int          get_data(void * buffer, int offset, int size);
426
427      /** Returns a \Ref{ByteStream} to access contents of the #DataPool#
428          sequentially. By reading from the returned stream you basically
429          call \Ref{get_data}() function. Thus, everything said for it
430          remains true for the stream too. */
431   GP<ByteStream>       get_stream(void);
432      //@}
433
434      /** @name State querying functions. */
435      //@{
436      /** Returns #TRUE# if this #DataPool# is connected to another #DataPool#
437          or to a file. */
438   bool         is_connected(void) const;
439   
440      /** Returns #TRUE# if all data available for offsets from
441          #start# till #start+length-1#. If #length# is negative, the
442          range is assumed to extend up to the end of the #DataPool#.
443          This function works both for connected and not connected #DataPool#s.
444          Once it returned #TRUE# for some offsets range, you can be
445          sure that the subsequent \Ref{get_data}() request will not block.
446      */
447   bool         has_data(int start, int length);
448
449      /* Returns #TRUE# if no more data is planned to be added.
450
451         {\bf Note:} This function always returns #TRUE# when the #DataPool#
452         has been initialized with a file name. */
453   bool         is_eof(void) const {return eof_flag;}
454
455      /** Returns the {\em length} of data in the #DataPool#. The value
456          returned depends on the mode of operation:
457          \begin{itemize}
458             \item If the #DataPool# is not connected to anything then
459                   the length returned is either calculated by interpreting
460                   the IFF structure of stored data (if successful) or
461                   by calculating the real size of data after \Ref{set_eof}()
462                   has been called. Otherwise it is #-1#.
463             \item If the #DataPool# is connected to a file, the length
464                   is calculated basing on the length passed to the
465                   \Ref{connect}() function and the file size.
466             \item If the #DataPool# is connected to a master #DataPool#,
467                   the length is calculated basing on the value returned
468                   by the master's #get_length()# function and the length
469                   passed to the \Ref{connect}() function.
470          \end{itemize}. */
471   int          get_length(void) const;
472      /** Returns the number of bytes of data available in this #DataPool#.
473          Contrary to the \Ref{get_length}() function, this one doesn't try
474          to interpret the IFF structure and predict the file length.
475          It just returns the number of bytes of data really available inside
476          the #DataPool#, if it contains data, or inside its range, if it's
477          connected to another #DataPool# or a file. */
478   int          get_size(void) const {return get_size(0, -1);}
479      //@}
480
481      /** @name Trigger callbacks.
482          {\em Trigger callbacks} are special callbacks called when
483          all data for the given range of offsets has been made available.
484          Since reading unavailable data may result in a thread block,
485          which may be bad, the usage of {\em trigger callbacks} appears
486          to be a convenient way to signal availability of data.
487
488          You can add a trigger callback in two ways:
489          \begin{enumerate}
490             \item By specifying a range. This is the most general case
491             \item By providing just one {\em threshold}. In this case
492                   the range is assumed to start from offset #ZERO# and
493                   last for {\em threshold}+1 bytes.
494          \end{enumerate}
495        */
496      //@{
497      /** Associates the specified {\em trigger callback} with the
498          given data range.
499
500          {\bf Note:} The callback may be called immediately if all
501          data for the given range is already available or #EOF# is #TRUE#.
502
503          @param start The beginning of the range for which all data
504                 should be available
505          @param length If the {\em length} is not negative then the callback
506                 will be called when there is data available for every
507                 offset from {\em start} to {\em start+length-1}.
508                 If {\em thresh} is negative, the callback is called after
509                 #EOF# condition has been set.
510          @param callback Function to call
511          @param cl_data Argument to pass to the callback when it's called. */
512   void         add_trigger(int start, int length,
513                            void (* callback)(void *), void * cl_data);
514
515      /** Associates the specified {\em trigger callback} with the
516          specified threshold.
517
518          This function is a simplified version of the function above.
519          The callback will be called when there is data available for
520          every offset from #0# to #thresh#, if #thresh# is positive, or
521          when #EOF# condition has been set otherwise. */
522
523   void         add_trigger(int thresh, 
524                            void (* callback)(void *), void * cl_data);
525
526      /** Use this function to unregister callbacks, which are no longer
527          needed. {\bf Note!} It's important to do it when the client
528          is about to be destroyed. */
529   void         del_trigger(void (* callback)(void *), void *  cl_data);
530
531      //@}
532
533      /** Loads data from the file into memory. This function is only useful
534          for #DataPool#s getting data from a file. It descends the #DataPool#s
535          hierarchy until it either reaches a file-connected #DataPool#
536          or #DataPool# containing the real data. In the latter case it
537          does nothing, in the first case it makes the #DataPool# read all
538          data from the file into memory and stop using the file.
539
540          This may be useful when you want to overwrite the file and leave
541          existing #DataPool#s with valid data. */
542   void         load_file(void);
543      /** This function will make every #DataPool# in the program, which
544          is connected to a file, to load the file contents to the main
545          memory and close the file. This feature is important when you
546          want to do something with the file like remove or overwrite it
547          not affecting the rest of the program. */
548   static void  load_file(const GURL &url);
549
550      /** This function will remove OpenFiles filelist. */
551   static void  close_all(void);
552
553      // Internal. Used by 'OpenFiles'
554   void         clear_stream(const bool release = true);
555
556      /** Useful in comparing data pools.  Returns true if dirived from
557          same URL or bytestream. */
558   bool simple_compare(DataPool &pool) const;
559
560
561private:
562   bool         eof_flag;
563   bool         stop_flag;
564   bool         stop_blocked_flag;
565
566   Counter      *active_readers;
567   
568      // Source or storage of data
569   GP<DataPool>         pool;
570   GURL         furl;
571   GP<OpenFiles_File>   fstream;
572   GCriticalSection     class_stream_lock;
573   GP<ByteStream>       data;
574   GCriticalSection     data_lock;
575   BlockList            *block_list;
576   int                  add_at;
577   int                  start, length;
578
579      // List of readers waiting for data
580   GPList<Reader>       readers_list;
581   GCriticalSection     readers_lock;
582
583      // Triggers
584   GPList<Trigger>      triggers_list;          // List of passed or our triggers
585   GCriticalSection     triggers_lock;          // Lock for the list above
586   GCriticalSection     trigger_lock;           // Lock for static_trigger_cb()
587
588   void         init(void);
589   void         wait_for_data(const GP<Reader> & reader);
590   void         wake_up_all_readers(void);
591   void         check_triggers(void);
592   int          get_data(void * buffer, int offset, int size, int level);
593   int          get_size(int start, int length) const;
594   void         restart_readers(void);
595
596//   static void        static_trigger_cb(GP<GPEnabled> &);
597   static void  static_trigger_cb(void *);
598   void         trigger_cb(void);
599   void         analyze_iff(void);
600   void         added_data(const int offset, const int size);
601public:
602  static const char *Stop;
603  friend class FCPools;
604};
605
606inline bool 
607DataPool::simple_compare(DataPool &pool) const
608{
609  // return true if these pools are identical.  False means they may or may
610  // not be identical.
611  return (this == &pool)
612    ||(furl.is_valid()&&!furl.is_empty()&&pool.furl.is_valid()&&(furl == pool.furl))
613    ||(data && (data == pool.data));
614}
615
616inline bool
617DataPool::is_connected(void) const
618{
619   return furl.is_local_file_url() || pool!=0;
620}
621
622//@}
623
624
625#ifdef HAVE_NAMESPACES
626}
627# ifndef NOT_USING_DJVU_NAMESPACE
628using namespace DJVU;
629# endif
630#endif
631#endif
Note: See TracBrowser for help on using the repository browser.