|
Packit |
df99a1 |
//C- -*- C++ -*-
|
|
Packit |
df99a1 |
//C- -------------------------------------------------------------------
|
|
Packit |
df99a1 |
//C- DjVuLibre-3.5
|
|
Packit |
df99a1 |
//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
|
|
Packit |
df99a1 |
//C- Copyright (c) 2001 AT&T
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- This software is subject to, and may be distributed under, the
|
|
Packit |
df99a1 |
//C- GNU General Public License, either Version 2 of the license,
|
|
Packit |
df99a1 |
//C- or (at your option) any later version. The license should have
|
|
Packit |
df99a1 |
//C- accompanied the software or you may obtain a copy of the license
|
|
Packit |
df99a1 |
//C- from the Free Software Foundation at http://www.fsf.org .
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- This program is distributed in the hope that it will be useful,
|
|
Packit |
df99a1 |
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
df99a1 |
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
df99a1 |
//C- GNU General Public License for more details.
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
|
|
Packit |
df99a1 |
//C- Lizardtech Software. Lizardtech Software has authorized us to
|
|
Packit |
df99a1 |
//C- replace the original DjVu(r) Reference Library notice by the following
|
|
Packit |
df99a1 |
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- ------------------------------------------------------------------
|
|
Packit |
df99a1 |
//C- | DjVu (r) Reference Library (v. 3.5)
|
|
Packit |
df99a1 |
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
|
|
Packit |
df99a1 |
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
|
|
Packit |
df99a1 |
//C- | 6,058,214 and patents pending.
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | This software is subject to, and may be distributed under, the
|
|
Packit |
df99a1 |
//C- | GNU General Public License, either Version 2 of the license,
|
|
Packit |
df99a1 |
//C- | or (at your option) any later version. The license should have
|
|
Packit |
df99a1 |
//C- | accompanied the software or you may obtain a copy of the license
|
|
Packit |
df99a1 |
//C- | from the Free Software Foundation at http://www.fsf.org .
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | The computer code originally released by LizardTech under this
|
|
Packit |
df99a1 |
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
|
|
Packit |
df99a1 |
//C- | ORIGINAL CODE." Subject to any third party intellectual property
|
|
Packit |
df99a1 |
//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
|
|
Packit |
df99a1 |
//C- | non-exclusive license to make, use, sell, or otherwise dispose of
|
|
Packit |
df99a1 |
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
|
|
Packit |
df99a1 |
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
|
|
Packit |
df99a1 |
//C- | General Public License. This grant only confers the right to
|
|
Packit |
df99a1 |
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
|
|
Packit |
df99a1 |
//C- | the extent such infringement is reasonably necessary to enable
|
|
Packit |
df99a1 |
//C- | recipient to make, have made, practice, sell, or otherwise dispose
|
|
Packit |
df99a1 |
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
|
|
Packit |
df99a1 |
//C- | any greater extent that may be necessary to utilize further
|
|
Packit |
df99a1 |
//C- | modifications or combinations.
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
|
|
Packit |
df99a1 |
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
Packit |
df99a1 |
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
|
|
Packit |
df99a1 |
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
df99a1 |
//C- +------------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef _GCONTAINER_H_
|
|
Packit |
df99a1 |
#define _GCONTAINER_H_
|
|
Packit |
df99a1 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
df99a1 |
#include "config.h"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#if NEED_GNUG_PRAGMAS
|
|
Packit |
df99a1 |
# pragma interface
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#include "GException.h"
|
|
Packit |
df99a1 |
#include "GSmartPointer.h"
|
|
Packit |
df99a1 |
#include <string.h>
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef HAVE_NAMESPACES
|
|
Packit |
df99a1 |
namespace DJVU {
|
|
Packit |
df99a1 |
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Supports old iterators (first/last/next/prev) on lists and maps?
|
|
Packit |
df99a1 |
#ifndef GCONTAINER_OLD_ITERATORS
|
|
Packit |
df99a1 |
#define GCONTAINER_OLD_ITERATORS 1
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Check array bounds at runtime ?
|
|
Packit |
df99a1 |
#ifndef GCONTAINER_BOUNDS_CHECK
|
|
Packit |
df99a1 |
#define GCONTAINER_BOUNDS_CHECK 1
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Clears allocated memory prior to running constructors ?
|
|
Packit |
df99a1 |
#ifndef GCONTAINER_ZERO_FILL
|
|
Packit |
df99a1 |
#define GCONTAINER_ZERO_FILL 1
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Avoid member templates (needed by old compilers)
|
|
Packit |
df99a1 |
#ifndef GCONTAINER_NO_MEMBER_TEMPLATES
|
|
Packit |
df99a1 |
#if defined(__GNUC__) && (__GNUC__==2) && (__GNUC_MINOR__<91)
|
|
Packit |
df99a1 |
#define GCONTAINER_NO_MEMBER_TEMPLATES 1
|
|
Packit |
df99a1 |
#elif defined(_MSC_VER) && !defined(__ICL)
|
|
Packit |
df99a1 |
#define GCONTAINER_NO_MEMBER_TEMPLATES 1
|
|
Packit |
df99a1 |
#elif defined(__MWERKS__)
|
|
Packit |
df99a1 |
#define GCONTAINER_NO_MEMBER_TEMPLATES 1
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
#define GCONTAINER_NO_MEMBER_TEMPLATES 0
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Define typename when needed
|
|
Packit |
df99a1 |
#ifndef GCONTAINER_NO_TYPENAME
|
|
Packit |
df99a1 |
#define GCONTAINER_NO_TYPENAME 0
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#if GCONTAINER_NO_TYPENAME
|
|
Packit |
df99a1 |
#define typename /**/
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name GContainer.h
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Files #"GContainer.h"# and #"GContainer.cpp"# implement three main
|
|
Packit |
df99a1 |
template class for generic containers.
|
|
Packit |
df99a1 |
Class #GArray# (see \Ref{Dynamic Arrays}) implements an array of objects
|
|
Packit |
df99a1 |
with variable bounds. Class #GList# (see \Ref{Doubly Linked Lists})
|
|
Packit |
df99a1 |
implements a doubly linked list of objects. Class #GMap# (see
|
|
Packit |
df99a1 |
\Ref{Associative Maps}) implements a hashed associative map. The
|
|
Packit |
df99a1 |
container templates are not thread-safe. Thread safety can be implemented
|
|
Packit |
df99a1 |
using the facilities provided in \Ref{GThreads.h}.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
@memo
|
|
Packit |
df99a1 |
Template class for generic containers.
|
|
Packit |
df99a1 |
@author
|
|
Packit |
df99a1 |
L\'eon Bottou <leonb@research.att.com> -- initial implementation.\\
|
|
Packit |
df99a1 |
Andrei Erofeev <eaf@geocities.com> -- bug fixes.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
// HASH FUNCTIONS
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name Hash functions
|
|
Packit |
df99a1 |
These functions let you use template class \Ref{GMap} with the
|
|
Packit |
df99a1 |
corresponding elementary types. The returned hash code may be reduced to
|
|
Packit |
df99a1 |
an arbitrary range by computing its remainder modulo the upper bound of
|
|
Packit |
df99a1 |
the range.
|
|
Packit |
df99a1 |
@memo Hash functions for elementary types. */
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (unsigned int). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const unsigned int & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (int). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const int & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (unsigned int)x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (long). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const long & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (unsigned int)x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (unsigned long). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const unsigned long & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (unsigned int)x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (const void *). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const void * const & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (unsigned int)(size_t) x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (float). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const float & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// optimizer will get rid of unnecessary code
|
|
Packit |
df99a1 |
unsigned int *addr = (unsigned int*)&x;
|
|
Packit |
df99a1 |
if (sizeof(float)<2*sizeof(unsigned int))
|
|
Packit |
df99a1 |
return addr[0];
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
return addr[0]^addr[1];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Hashing function (double). */
|
|
Packit |
df99a1 |
static inline unsigned int
|
|
Packit |
df99a1 |
hash(const double & x)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// optimizer will get rid of unnecessary code
|
|
Packit |
df99a1 |
unsigned int *addr = (unsigned int*)&x;
|
|
Packit |
df99a1 |
if (sizeof(double)<2*sizeof(unsigned int))
|
|
Packit |
df99a1 |
return addr[0];
|
|
Packit |
df99a1 |
else if (sizeof(double)<4*sizeof(unsigned int))
|
|
Packit |
df99a1 |
return addr[0]^addr[1];
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
return addr[0]^addr[1]^addr[2]^addr[3];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
// HELPER CLASSES
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Namespace for containers support classes. This class is used as a
|
|
Packit |
df99a1 |
namespace for global identifiers related to the implementation of
|
|
Packit |
df99a1 |
containers. It is inherited by all container objects. This is disabled by
|
|
Packit |
df99a1 |
defining compilation symbol #GCONTAINER_NO_MEMBER_TEMPATES# to 1. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef _MSC_VER
|
|
Packit |
df99a1 |
// Language lawyer say MS is wrong on that one.
|
|
Packit |
df99a1 |
// Cf section 5.4.7 in november 1997 draft.
|
|
Packit |
df99a1 |
#pragma warning( disable : 4243 )
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// GPEnabled inhertenced removed again so the code works on more machines.
|
|
Packit |
df99a1 |
class GCont
|
|
Packit |
df99a1 |
#if GCONTAINER_NO_MEMBER_TEMPLATES
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
// --- Pointers to type management functions
|
|
Packit |
df99a1 |
struct Traits
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int size;
|
|
Packit |
df99a1 |
void *(*lea) (void *base, int n);
|
|
Packit |
df99a1 |
void (*init) (void *dst, int n);
|
|
Packit |
df99a1 |
void (*copy) (void *dst, const void* src, int n, int zap);
|
|
Packit |
df99a1 |
void (*fini) (void *dst, int n);
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
#if !GCONTAINER_NO_MEMBER_TEMPLATES
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
// --- Management of simple types
|
|
Packit |
df99a1 |
template <int SZ> class TrivTraits
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// The unique object
|
|
Packit |
df99a1 |
static const Traits & traits();
|
|
Packit |
df99a1 |
// Offset in an array of T
|
|
Packit |
df99a1 |
static void * lea(void* base, int n)
|
|
Packit |
df99a1 |
{ return (void*)( ((char*)base) + SZ*n ); }
|
|
Packit |
df99a1 |
// Trivial default constructor
|
|
Packit |
df99a1 |
static void init(void* dst, int n) {}
|
|
Packit |
df99a1 |
// Trivial copy constructor
|
|
Packit |
df99a1 |
static void copy(void* dst, const void* src, int n, int )
|
|
Packit |
df99a1 |
{ ::memcpy(dst, src, SZ*n); }
|
|
Packit |
df99a1 |
// Trivial destructor
|
|
Packit |
df99a1 |
static void fini(void* dst, int n) {}
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// --- Management of regular types
|
|
Packit |
df99a1 |
template <class T> class NormTraits
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// The unique object
|
|
Packit |
df99a1 |
static const Traits & traits();
|
|
Packit |
df99a1 |
// Offset in an array of T
|
|
Packit |
df99a1 |
static void * lea(void* base, int n)
|
|
Packit |
df99a1 |
{ return (void*)( ((T*)base) + n ); }
|
|
Packit |
df99a1 |
// Template based default constructor
|
|
Packit |
df99a1 |
static void init(void* dst, int n)
|
|
Packit |
df99a1 |
{ T* d = (T*)dst; while (--n>=0) { new ((void*)d) T; d++; } }
|
|
Packit |
df99a1 |
// Template based copy constructor
|
|
Packit |
df99a1 |
static void copy(void* dst, const void* src, int n, int zap)
|
|
Packit |
df99a1 |
{ T* d = (T*)dst; T* s = (T*)src; while (--n>=0) {
|
|
Packit |
df99a1 |
new ((void*)d) T(*s); if (zap) { s->~T(); }; d++; s++; } }
|
|
Packit |
df99a1 |
// Template based destructor
|
|
Packit |
df99a1 |
static void fini(void* dst, int n)
|
|
Packit |
df99a1 |
{ T* d = (T*)dst; while (--n>=0) { d->~T(); d++; } }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// --- Base class for list nodes
|
|
Packit |
df99a1 |
struct Node
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
Node *next;
|
|
Packit |
df99a1 |
Node *prev;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// -- Class for list nodes
|
|
Packit |
df99a1 |
template <class T> struct ListNode : public Node
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
T val;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// -- Class for map nodes showing the hash
|
|
Packit |
df99a1 |
struct HNode : public Node
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
HNode *hprev;
|
|
Packit |
df99a1 |
unsigned int hashcode;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// -- Class for map nodes showing the hash and the key
|
|
Packit |
df99a1 |
template <class K> struct SetNode : public HNode
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
K key;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
// -- Class for map nodes with everything
|
|
Packit |
df99a1 |
template <class K, class T> struct MapNode : public SetNode<K>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
T val;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
#if !GCONTAINER_NO_MEMBER_TEMPLATES
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#if !GCONTAINER_NO_MEMBER_TEMPLATES
|
|
Packit |
df99a1 |
#define GCONT GCont::
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
#define GCONT
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <int SZ> const GCONT Traits &
|
|
Packit |
df99a1 |
GCONT TrivTraits<SZ>::traits()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static const Traits theTraits = {
|
|
Packit |
df99a1 |
SZ,
|
|
Packit |
df99a1 |
TrivTraits<SZ>::lea,
|
|
Packit |
df99a1 |
TrivTraits<SZ>::init,
|
|
Packit |
df99a1 |
TrivTraits<SZ>::copy,
|
|
Packit |
df99a1 |
TrivTraits<SZ>::fini
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
return theTraits;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class T> const GCONT Traits &
|
|
Packit |
df99a1 |
GCONT NormTraits<T>::traits()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static const Traits theTraits = {
|
|
Packit |
df99a1 |
sizeof(T),
|
|
Packit |
df99a1 |
NormTraits<T>::lea,
|
|
Packit |
df99a1 |
NormTraits<T>::init,
|
|
Packit |
df99a1 |
NormTraits<T>::copy,
|
|
Packit |
df99a1 |
NormTraits<T>::fini
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
return theTraits;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
// DYNAMIC ARRAYS
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name Dynamic Arrays
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
These class implement arrays of objects of any type. Each element is
|
|
Packit |
df99a1 |
identified by an integer subscript. The valid subscripts range is defined
|
|
Packit |
df99a1 |
by dynamically adjustable lower- and upper-bounds. Besides accessing and
|
|
Packit |
df99a1 |
setting elements, member functions are provided to insert or delete
|
|
Packit |
df99a1 |
elements at specified positions.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Class \Ref{GArrayTemplate} implements all methods for manipulating arrays
|
|
Packit |
df99a1 |
of type #TYPE#. You should not however create instances of this class.
|
|
Packit |
df99a1 |
You should instead use one of the following classes:
|
|
Packit |
df99a1 |
\begin{itemize}
|
|
Packit |
df99a1 |
\item Class \Ref{GArray<TYPE>} is the most general class,
|
|
Packit |
df99a1 |
\item Class \Ref{GTArray<TYPE>} is more efficient, but only works for
|
|
Packit |
df99a1 |
types that do not require sophisticated constructors or destructors,
|
|
Packit |
df99a1 |
such as the plain old C types (e.g. #int# or #char# ...).
|
|
Packit |
df99a1 |
\item Class \Ref{GPArray<TYPE>} implements an array of smart-pointers
|
|
Packit |
df99a1 |
\Ref{GP<TYPE>} to objects of type #TYPE#. Using this class
|
|
Packit |
df99a1 |
reduces the size of the code generated by the template instanciation.
|
|
Packit |
df99a1 |
\end{itemize}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Another variant of dynamic arrays is implemented in file \Ref{Arrays.h}.
|
|
Packit |
df99a1 |
The main difference is that class \Ref{TArray}, \Ref{DArray} and
|
|
Packit |
df99a1 |
\Ref{DPArray} implement a copy-on-demand scheme.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
@memo Dynamic arrays. */
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI GArrayBase : public GCont
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// -- CONSTRUCTORS
|
|
Packit |
df99a1 |
GArrayBase(const GArrayBase &ref;;
|
|
Packit |
df99a1 |
GArrayBase(const Traits &traits);
|
|
Packit |
df99a1 |
GArrayBase(const Traits &traits, int lobound, int hibound);
|
|
Packit |
df99a1 |
// -- DESTRUCTOR
|
|
Packit |
df99a1 |
~GArrayBase();
|
|
Packit |
df99a1 |
// -- ASSIGNMENT
|
|
Packit |
df99a1 |
GArrayBase& operator= (const GArrayBase &ga);
|
|
Packit |
df99a1 |
// -- ALTERATION
|
|
Packit |
df99a1 |
void empty();
|
|
Packit |
df99a1 |
void touch(int n);
|
|
Packit |
df99a1 |
void resize(int lobound, int hibound);
|
|
Packit |
df99a1 |
void shift(int disp);
|
|
Packit |
df99a1 |
void del(int n, int howmany=1);
|
|
Packit |
df99a1 |
void ins(int n, const void *src, int howmany=1);
|
|
Packit |
df99a1 |
void steal(GArrayBase &ga);
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
const Traits &traits;
|
|
Packit |
df99a1 |
void *data;
|
|
Packit |
df99a1 |
int minlo;
|
|
Packit |
df99a1 |
int maxhi;
|
|
Packit |
df99a1 |
int lobound;
|
|
Packit |
df99a1 |
int hibound;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Common base class for all dynamic arrays.
|
|
Packit |
df99a1 |
Class \Ref{GArrayTemplate} implements all methods for manipulating arrays
|
|
Packit |
df99a1 |
of type #TYPE#. You should not however create instances of this class.
|
|
Packit |
df99a1 |
You should instead use class \Ref{GArray}, \Ref{GTArray} or
|
|
Packit |
df99a1 |
\Ref{GPArray}. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TYPE>
|
|
Packit |
df99a1 |
class GArrayTemplate : protected GArrayBase
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// -- CONSTRUCTORS
|
|
Packit |
df99a1 |
GArrayTemplate(const Traits &traits) : GArrayBase(traits) {}
|
|
Packit |
df99a1 |
GArrayTemplate(const Traits &traits, int lobound, int hibound)
|
|
Packit |
df99a1 |
: GArrayBase(traits, lobound, hibound) {}
|
|
Packit |
df99a1 |
// -- ACCESS
|
|
Packit |
df99a1 |
/** Returns the number of elements in the array. */
|
|
Packit |
df99a1 |
int size() const
|
|
Packit |
df99a1 |
{ return hibound-lobound+1; }
|
|
Packit |
df99a1 |
/** Returns the lower bound of the valid subscript range. */
|
|
Packit |
df99a1 |
int lbound() const
|
|
Packit |
df99a1 |
{ return lobound; }
|
|
Packit |
df99a1 |
/** Returns the upper bound of the valid subscript range. */
|
|
Packit |
df99a1 |
int hbound() const
|
|
Packit |
df99a1 |
{ return hibound; }
|
|
Packit |
df99a1 |
/** Returns a reference to the array element for subscript #n#. This
|
|
Packit |
df99a1 |
reference can be used for both reading (as "#a[n]#") and writing (as
|
|
Packit |
df99a1 |
"#a[n]=v#") an array element. This operation will not extend the valid
|
|
Packit |
df99a1 |
subscript range: an exception \Ref{GException} is thrown if argument #n#
|
|
Packit |
df99a1 |
is not in the valid subscript range. */
|
|
Packit |
df99a1 |
inline TYPE& operator[](int const n);
|
|
Packit |
df99a1 |
/** Returns a constant reference to the array element for subscript #n#.
|
|
Packit |
df99a1 |
This reference can only be used for reading (as "#a[n]#") an array
|
|
Packit |
df99a1 |
element. This operation will not extend the valid subscript range: an
|
|
Packit |
df99a1 |
exception \Ref{GException} is thrown if argument #n# is not in the valid
|
|
Packit |
df99a1 |
subscript range. This variant of #operator[]# is necessary when dealing
|
|
Packit |
df99a1 |
with a #const GArray<TYPE>#. */
|
|
Packit |
df99a1 |
inline const TYPE& operator[](int n) const;
|
|
Packit |
df99a1 |
// -- CONVERSION
|
|
Packit |
df99a1 |
/** Returns a pointer for reading or writing the array elements. This
|
|
Packit |
df99a1 |
pointer can be used to access the array elements with the same
|
|
Packit |
df99a1 |
subscripts and the usual bracket syntax. This pointer remains valid as
|
|
Packit |
df99a1 |
long as the valid subscript range is unchanged. If you change the
|
|
Packit |
df99a1 |
subscript range, you must stop using the pointers returned by prior
|
|
Packit |
df99a1 |
invocation of this conversion operator. */
|
|
Packit |
df99a1 |
operator TYPE* ()
|
|
Packit |
df99a1 |
{ return ((TYPE*)data)-minlo; }
|
|
Packit |
df99a1 |
/** Returns a pointer for reading (but not modifying) the array elements.
|
|
Packit |
df99a1 |
This pointer can be used to access the array elements with the same
|
|
Packit |
df99a1 |
subscripts and the usual bracket syntax. This pointer remains valid as
|
|
Packit |
df99a1 |
long as the valid subscript range is unchanged. If you change the
|
|
Packit |
df99a1 |
subscript range, you must stop using the pointers returned by prior
|
|
Packit |
df99a1 |
invocation of this conversion operator. */
|
|
Packit |
df99a1 |
operator const TYPE* () const
|
|
Packit |
df99a1 |
{ return ((const TYPE*)data)-minlo; }
|
|
Packit |
df99a1 |
// -- ALTERATION
|
|
Packit |
df99a1 |
/** Erases the array contents. All elements in the array are destroyed.
|
|
Packit |
df99a1 |
The valid subscript range is set to the empty range. */
|
|
Packit |
df99a1 |
void empty()
|
|
Packit |
df99a1 |
{ GArrayBase::empty(); }
|
|
Packit |
df99a1 |
/** Extends the subscript range so that it contains #n#.
|
|
Packit |
df99a1 |
This function does nothing if #n# is already int the valid subscript range.
|
|
Packit |
df99a1 |
If the valid range was empty, both the lower bound and the upper bound
|
|
Packit |
df99a1 |
are set to #n#. Otherwise the valid subscript range is extended
|
|
Packit |
df99a1 |
to encompass #n#. This function is very handy when called before setting
|
|
Packit |
df99a1 |
an array element:
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
int lineno=1;
|
|
Packit |
df99a1 |
GArray<GString> a;
|
|
Packit |
df99a1 |
while (! end_of_file()) {
|
|
Packit |
df99a1 |
a.touch(lineno);
|
|
Packit |
df99a1 |
a[lineno++] = read_a_line();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
\end{verbatim} */
|
|
Packit |
df99a1 |
void touch(int n)
|
|
Packit |
df99a1 |
{ if (n<lobound || n>hibound) GArrayBase::touch(n); }
|
|
Packit |
df99a1 |
/** Resets the valid subscript range to #0#---#hibound#.
|
|
Packit |
df99a1 |
This function may destroy some array elements and may construct
|
|
Packit |
df99a1 |
new array elements with the null constructor. Setting #hibound# to
|
|
Packit |
df99a1 |
#-1# resets the valid subscript range to the empty range. */
|
|
Packit |
df99a1 |
void resize(int hibound)
|
|
Packit |
df99a1 |
{ GArrayBase::resize(0, hibound); }
|
|
Packit |
df99a1 |
/** Resets the valid subscript range to #lobound#---#hibound#.
|
|
Packit |
df99a1 |
This function may destroy some array elements and may construct
|
|
Packit |
df99a1 |
new array elements with the null constructor. Setting #lobound# to #0# and
|
|
Packit |
df99a1 |
#hibound# to #-1# resets the valid subscript range to the empty range. */
|
|
Packit |
df99a1 |
void resize(int lobound, int hibound)
|
|
Packit |
df99a1 |
{ GArrayBase::resize(lobound, hibound); }
|
|
Packit |
df99a1 |
/** Shifts the valid subscript range. Argument #disp# is added to both
|
|
Packit |
df99a1 |
bounds of the valid subscript range. Array elements previously
|
|
Packit |
df99a1 |
located at subscript #x# will now be located at subscript #x+disp#. */
|
|
Packit |
df99a1 |
void shift(int disp)
|
|
Packit |
df99a1 |
{ GArrayBase::shift(disp); }
|
|
Packit |
df99a1 |
/** Deletes array elements. The array elements corresponding to
|
|
Packit |
df99a1 |
subscripts #n#...#n+howmany-1# are destroyed. All array elements
|
|
Packit |
df99a1 |
previously located at subscripts greater or equal to #n+howmany#
|
|
Packit |
df99a1 |
are moved to subscripts starting with #n#. The new subscript upper
|
|
Packit |
df99a1 |
bound is reduced in order to account for this shift. */
|
|
Packit |
df99a1 |
void del(int n, int howmany=1)
|
|
Packit |
df99a1 |
{ GArrayBase::del(n, howmany); }
|
|
Packit |
df99a1 |
/** Insert new elements into an array. This function inserts
|
|
Packit |
df99a1 |
#howmany# elements at position #n# into the array. These
|
|
Packit |
df99a1 |
elements are constructed using the default constructor for type
|
|
Packit |
df99a1 |
#TYPE#. All array elements previously located at subscripts #n#
|
|
Packit |
df99a1 |
and higher are moved to subscripts #n+howmany# and higher. The
|
|
Packit |
df99a1 |
upper bound of the valid subscript range is increased in order
|
|
Packit |
df99a1 |
to account for this shift. */
|
|
Packit |
df99a1 |
void ins(int n, int howmany=1)
|
|
Packit |
df99a1 |
{ GArrayBase::ins(n, 0, howmany); }
|
|
Packit |
df99a1 |
/** Insert new elements into an array. The new elements are
|
|
Packit |
df99a1 |
constructed by copying element #val# using the copy constructor
|
|
Packit |
df99a1 |
for type #TYPE#. See \Ref{ins(int n, unsigned int howmany=1)}. */
|
|
Packit |
df99a1 |
void ins(int n, const TYPE &val, int howmany=1)
|
|
Packit |
df99a1 |
{ GArrayBase::ins(n, (const void*)&val, howmany); }
|
|
Packit |
df99a1 |
/** Steals contents from array #ga#. After this call, array #ga# is empty,
|
|
Packit |
df99a1 |
and this array contains everything previously contained in #ga#. */
|
|
Packit |
df99a1 |
void steal(GArrayTemplate &ga)
|
|
Packit |
df99a1 |
{ GArrayBase::steal(ga); }
|
|
Packit |
df99a1 |
// -- SORTING
|
|
Packit |
df99a1 |
/** Sort array elements. Sort all array elements in ascending
|
|
Packit |
df99a1 |
order according to the less-or-equal comparison
|
|
Packit |
df99a1 |
operator for type #TYPE#. */
|
|
Packit |
df99a1 |
void sort()
|
|
Packit |
df99a1 |
{ sort(lbound(), hbound()); }
|
|
Packit |
df99a1 |
/** Sort array elements in subscript range #lo# to #hi#. Sort all array
|
|
Packit |
df99a1 |
elements whose subscripts are in range #lo# to #hi# in ascending order
|
|
Packit |
df99a1 |
according to the less-or-equal comparison operator for type #TYPE#. The
|
|
Packit |
df99a1 |
other elements of the array are left untouched. An exception is thrown
|
|
Packit |
df99a1 |
if arguments #lo# and #hi# are not in the valid subscript range. */
|
|
Packit |
df99a1 |
void sort(int lo, int hi);
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* That one must be implemented as a regular template function. */
|
|
Packit |
df99a1 |
template <class TYPE> void
|
|
Packit |
df99a1 |
GArrayTemplate<TYPE>::sort(int lo, int hi)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (hi <= lo)
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
if (hi > hibound || lo
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("GContainer.illegal_subscript") );
|
|
Packit |
df99a1 |
TYPE *data = (TYPE*)(*this);
|
|
Packit |
df99a1 |
// Test for insertion sort
|
|
Packit |
df99a1 |
if (hi <= lo + 50)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
for (int i=lo+1; i<=hi; i++)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int j = i;
|
|
Packit |
df99a1 |
TYPE tmp = data[i];
|
|
Packit |
df99a1 |
while ((--j>=lo) && !(data[j]<=tmp))
|
|
Packit |
df99a1 |
data[j+1] = data[j];
|
|
Packit |
df99a1 |
data[j+1] = tmp;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// -- determine suitable quick-sort pivot
|
|
Packit |
df99a1 |
TYPE tmp = data[lo];
|
|
Packit |
df99a1 |
TYPE pivot = data[(lo+hi)/2];
|
|
Packit |
df99a1 |
if (pivot <= tmp)
|
|
Packit |
df99a1 |
{ tmp = pivot; pivot=data[lo]; }
|
|
Packit |
df99a1 |
if (data[hi] <= tmp)
|
|
Packit |
df99a1 |
{ pivot = tmp; }
|
|
Packit |
df99a1 |
else if (data[hi] <= pivot)
|
|
Packit |
df99a1 |
{ pivot = data[hi]; }
|
|
Packit |
df99a1 |
// -- partition set
|
|
Packit |
df99a1 |
int h = hi;
|
|
Packit |
df99a1 |
int l = lo;
|
|
Packit |
df99a1 |
while (l < h)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (! (pivot <= data[l])) l++;
|
|
Packit |
df99a1 |
while (! (data[h] <= pivot)) h--;
|
|
Packit |
df99a1 |
if (l < h)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
tmp = data[l];
|
|
Packit |
df99a1 |
data[l] = data[h];
|
|
Packit |
df99a1 |
data[h] = tmp;
|
|
Packit |
df99a1 |
l = l+1;
|
|
Packit |
df99a1 |
h = h-1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// -- recursively restart
|
|
Packit |
df99a1 |
sort(lo, h);
|
|
Packit |
df99a1 |
sort(l, hi);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TYPE> inline TYPE&
|
|
Packit |
df99a1 |
GArrayTemplate<TYPE>::operator[](int const n)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
#if GCONTAINER_BOUNDS_CHECK
|
|
Packit |
df99a1 |
if (n<lobound || n>hibound)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("GContainer.illegal_subscript") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
return ((TYPE*)data)[n-minlo];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TYPE> inline const TYPE &
|
|
Packit |
df99a1 |
GArrayTemplate<TYPE>::operator[](int const n) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
#if GCONTAINER_BOUNDS_CHECK
|
|
Packit |
df99a1 |
if (n<lobound || n>hibound)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("GContainer.illegal_subscript") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
return ((const TYPE*)data)[n-minlo];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Dynamic array for general types.
|
|
Packit |
df99a1 |
Template class #GArray<TYPE># implements an array of elements of type
|
|
Packit |
df99a1 |
#TYPE#. This template class must be able to access the following
|
|
Packit |
df99a1 |
functions.
|
|
Packit |
df99a1 |
\begin{itemize}
|
|
Packit |
df99a1 |
\item a default constructor #TYPE::TYPE()#,
|
|
Packit |
df99a1 |
\item a copy constructor #TYPE::TYPE(const TYPE &)#,
|
|
Packit |
df99a1 |
\item and optionally a destructor #TYPE::~TYPE()#.
|
|
Packit |
df99a1 |
\end{itemize}
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GArrayTemplate}
|
|
Packit |
df99a1 |
for a description of all access methods. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TYPE>
|
|
Packit |
df99a1 |
class GArray : public GArrayTemplate<TYPE>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
/** Constructs an empty array. The valid subscript range is initially
|
|
Packit |
df99a1 |
empty. Member function #touch# and #resize# provide convenient ways
|
|
Packit |
df99a1 |
to enlarge the subscript range. */
|
|
Packit |
df99a1 |
GArray()
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT NormTraits<TYPE>::traits() ) {}
|
|
Packit |
df99a1 |
/** Constructs an array with subscripts in range 0 to #hibound#.
|
|
Packit |
df99a1 |
The subscript range can be subsequently modified with member functions
|
|
Packit |
df99a1 |
#touch# and #resize#. */
|
|
Packit |
df99a1 |
GArray(int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT NormTraits<TYPE>::traits(), 0, hi ) {}
|
|
Packit |
df99a1 |
/** Constructs an array with subscripts in range #lobound# to #hibound#.
|
|
Packit |
df99a1 |
The subscript range can be subsequently modified with member functions
|
|
Packit |
df99a1 |
#touch# and #resize#. */
|
|
Packit |
df99a1 |
GArray(int lo, int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT NormTraits<TYPE>::traits(), lo, hi ) {}
|
|
Packit |
df99a1 |
// Copy operator
|
|
Packit |
df99a1 |
GArray& operator=(const GArray &r)
|
|
Packit |
df99a1 |
{ GArrayBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Dynamic array for smart pointers.
|
|
Packit |
df99a1 |
Template class #GPArray<TYPE># implements an array of elements of type
|
|
Packit |
df99a1 |
#GP<TYPE># (see \Ref{GSmartPointer.h}). Significantly smaller code sizes
|
|
Packit |
df99a1 |
can be achieved by using this class instead of the more general
|
|
Packit |
df99a1 |
#GArray<GP<TYPE>>#.
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GArrayTemplate}
|
|
Packit |
df99a1 |
for a description of all access methods. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TYPE>
|
|
Packit |
df99a1 |
class GPArray : public GArrayTemplate<GP<TYPE> >
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
GPArray()
|
|
Packit |
df99a1 |
: GArrayTemplate<GP<TYPE> >(GCONT NormTraits<GPBase>::traits() ) {}
|
|
Packit |
df99a1 |
GPArray(int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<GP<TYPE> >(GCONT NormTraits<GPBase>::traits(), 0, hi ) {}
|
|
Packit |
df99a1 |
GPArray(int lo, int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<GP<TYPE> >(GCONT NormTraits<GPBase>::traits(), lo, hi ) {}
|
|
Packit |
df99a1 |
// Copy operator
|
|
Packit |
df99a1 |
GPArray& operator=(const GPArray &r)
|
|
Packit |
df99a1 |
{ GArrayBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Dynamic array for simple types.
|
|
Packit |
df99a1 |
Template class #GTArray<TYPE># implements an array of elements of {\em
|
|
Packit |
df99a1 |
simple} type #TYPE#. {\em Simple} means that objects of type #TYPE# can
|
|
Packit |
df99a1 |
be created, copied, moved or destroyed without using specific constructors
|
|
Packit |
df99a1 |
or destructor functions. Class #GTArray<TYPE># will move or copy objects
|
|
Packit |
df99a1 |
using simple bitwise copies. Otherwise you must use class #GArray<TYPE>#.
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GArrayTemplate}
|
|
Packit |
df99a1 |
for a description of all access methods. */
|
|
Packit |
df99a1 |
template<class TYPE>
|
|
Packit |
df99a1 |
class GTArray : public GArrayTemplate<TYPE>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
GTArray()
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT TrivTraits<sizeof(TYPE)>::traits() ) {}
|
|
Packit |
df99a1 |
GTArray(int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT TrivTraits<sizeof(TYPE)>::traits(), 0, hi ) {}
|
|
Packit |
df99a1 |
GTArray(int lo, int hi)
|
|
Packit |
df99a1 |
: GArrayTemplate<TYPE>(GCONT TrivTraits<sizeof(TYPE)>::traits(), lo, hi ) {}
|
|
Packit |
df99a1 |
// Copy operator
|
|
Packit |
df99a1 |
GTArray& operator=(const GTArray &r)
|
|
Packit |
df99a1 |
{ GArrayBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
// DOUBLY LINKED LISTS
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name Doubly Linked Lists
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
The template classes \Ref{GList} and \Ref{GPList} implement a doubly
|
|
Packit |
df99a1 |
linked list of objects of arbitrary types. Member functions are provided
|
|
Packit |
df99a1 |
to search the list for an element, to insert or delete elements at
|
|
Packit |
df99a1 |
specified positions. Theses template class must be able to access
|
|
Packit |
df99a1 |
\begin{itemize}
|
|
Packit |
df99a1 |
\item a default constructor #TYPE::TYPE()#,
|
|
Packit |
df99a1 |
\item a copy constructor #TYPE::TYPE(const TYPE &)#,
|
|
Packit |
df99a1 |
\item optionally a destructor #TYPE::~TYPE()#,
|
|
Packit |
df99a1 |
\item and optionally a comparison operator #TYPE::operator==(const TYPE &)#.
|
|
Packit |
df99a1 |
\end{itemize}
|
|
Packit |
df99a1 |
@memo Doubly linked lists.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Generic iterator class.
|
|
Packit |
df99a1 |
This class represents a position in a list (see \Ref{GList}) or a map
|
|
Packit |
df99a1 |
(see \Ref{GMap}). As demonstrated by the following examples,
|
|
Packit |
df99a1 |
this class should be used to iterate over the objects contained
|
|
Packit |
df99a1 |
in a list or a map:
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
void print_list(GList<GString> a)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
for (GPosition i = a ; i; ++i)
|
|
Packit |
df99a1 |
DjVuPrintMessage("%s\n", (const char*) a[i] );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void print_list_backwards(GList<GString> a)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
for (GPosition i = a.lastpos() ; i; --i)
|
|
Packit |
df99a1 |
DjVuPrintMessage("%s\n", (const char*) a[i] );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
GPosition objects should only be used with the list or map for which they
|
|
Packit |
df99a1 |
have been created (using the member functions #firstpos# or #lastpos# of
|
|
Packit |
df99a1 |
the container). Furthermore, you should never use a GPosition object
|
|
Packit |
df99a1 |
which designates a list element which has been removed from the list
|
|
Packit |
df99a1 |
(using member function #del# or by other means.)
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI GPosition : protected GCont
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
/** Creates a null GPosition object. */
|
|
Packit |
df99a1 |
GPosition() : ptr(0), cont(0) {}
|
|
Packit |
df99a1 |
/** Creates a copy of a GPosition object. */
|
|
Packit |
df99a1 |
GPosition(const GPosition &ref) : ptr(ref.ptr), cont(ref.cont) {}
|
|
Packit |
df99a1 |
/** Tests whether this GPosition object is non null. */
|
|
Packit |
df99a1 |
operator int() const
|
|
Packit |
df99a1 |
{ return !!ptr; }
|
|
Packit |
df99a1 |
/** Tests whether this GPosition object is null. */
|
|
Packit |
df99a1 |
int operator !() const
|
|
Packit |
df99a1 |
{ return !ptr; }
|
|
Packit |
df99a1 |
/** Moves this GPosition object to the next object in the container. */
|
|
Packit |
df99a1 |
GPosition& operator ++()
|
|
Packit |
df99a1 |
{ if (ptr) ptr = ptr->next; return *this; }
|
|
Packit |
df99a1 |
/** Moves this GPosition object to the previous object in the container. */
|
|
Packit |
df99a1 |
GPosition& operator --()
|
|
Packit |
df99a1 |
{ if (ptr) ptr = ptr->prev; return *this; }
|
|
Packit |
df99a1 |
// Internal. Do not use.
|
|
Packit |
df99a1 |
GPosition(Node *p, void *c) : ptr(p), cont(c) {}
|
|
Packit |
df99a1 |
#if GCONTAINER_BOUNDS_CHECK
|
|
Packit |
df99a1 |
Node *check(void *c)
|
|
Packit |
df99a1 |
{ if (!ptr || c!=cont) throw_invalid(c); return ptr; }
|
|
Packit |
df99a1 |
const Node *check(void *c) const
|
|
Packit |
df99a1 |
{ if (!ptr || c!=cont) throw_invalid(c); return ptr; }
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
Node *check(void *c)
|
|
Packit |
df99a1 |
{ return ptr; }
|
|
Packit |
df99a1 |
const Node *check(void *c) const
|
|
Packit |
df99a1 |
{ return ptr; }
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
Node *ptr;
|
|
Packit |
df99a1 |
void *cont;
|
|
Packit |
df99a1 |
friend class GListBase;
|
|
Packit |
df99a1 |
friend class GSetBase;
|
|
Packit |
df99a1 |
void throw_invalid(void *c) const no_return;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI GListBase : public GCont
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GListBase(const Traits& traits);
|
|
Packit |
df99a1 |
GListBase(const GListBase &ref;;
|
|
Packit |
df99a1 |
void append(Node *n);
|
|
Packit |
df99a1 |
void prepend(Node *n);
|
|
Packit |
df99a1 |
void insert_after(GPosition pos, Node *n);
|
|
Packit |
df99a1 |
void insert_before(GPosition pos, Node *n);
|
|
Packit |
df99a1 |
void insert_before(GPosition pos, GListBase &fromlist, GPosition &frompos);
|
|
Packit |
df99a1 |
void del(GPosition &pos;;
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
const Traits &traits;
|
|
Packit |
df99a1 |
int nelem;
|
|
Packit |
df99a1 |
Node head;
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
~GListBase();
|
|
Packit |
df99a1 |
GListBase & operator= (const GListBase & gl);
|
|
Packit |
df99a1 |
GPosition firstpos() const { return GPosition(head.next, (void*)this); }
|
|
Packit |
df99a1 |
GPosition lastpos() const { return GPosition(head.prev, (void*)this); }
|
|
Packit |
df99a1 |
bool isempty() const { return nelem==0; };
|
|
Packit |
df99a1 |
GPosition nth(unsigned int n) const;
|
|
Packit |
df99a1 |
void empty();
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TI>
|
|
Packit |
df99a1 |
class GListImpl : public GListBase
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
typedef GCONT ListNode<TI> LNode;
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GListImpl();
|
|
Packit |
df99a1 |
static Node * newnode(const TI &elt;;
|
|
Packit |
df99a1 |
int operator==(const GListImpl<TI> &l2) const;
|
|
Packit |
df99a1 |
int search(const TI &elt, GPosition &pos) const;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TI>
|
|
Packit |
df99a1 |
GListImpl<TI>::GListImpl()
|
|
Packit |
df99a1 |
: GListBase( GCONT NormTraits<LNode>::traits() )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TI> GCONT Node *
|
|
Packit |
df99a1 |
GListImpl<TI>::newnode(const TI &elt)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
LNode *n = (LNode *) operator new (sizeof(LNode ));
|
|
Packit |
df99a1 |
#if GCONTAINER_ZERO_FILL
|
|
Packit |
df99a1 |
memset(n, 0, sizeof(LNode ));
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
new ((void*)&(n->val)) TI(elt);
|
|
Packit |
df99a1 |
return (Node*) n;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TI> int
|
|
Packit |
df99a1 |
GListImpl<TI>::operator==(const GListImpl<TI> &l2) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
Node *p, *q;
|
|
Packit |
df99a1 |
for (p=head.next, q=l2.head.next; p && q; p=p->next, q=q->next )
|
|
Packit |
df99a1 |
if (((LNode*)p)->val != ((LNode*)q)->val)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
return p==0 && q==0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class TI> int
|
|
Packit |
df99a1 |
GListImpl<TI>::search(const TI &elt, GPosition &pos) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
Node *n = (pos ? pos.check((void*)this) : head.next);
|
|
Packit |
df99a1 |
for (; n; n=n->next)
|
|
Packit |
df99a1 |
if ( ((LNode *)n)->val == elt )
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
if (n) pos = GPosition(n, (void*)this);
|
|
Packit |
df99a1 |
return (n != 0);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Common base class for all doubly linked lists.
|
|
Packit |
df99a1 |
Class \Ref{GListTemplate} implements all methods for manipulating lists
|
|
Packit |
df99a1 |
of of objects of type #TYPE#. You should not however create instances of
|
|
Packit |
df99a1 |
this class. You should instead use class \Ref{GList} or \Ref{GPList}. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class TYPE, class TI>
|
|
Packit |
df99a1 |
class GListTemplate : protected GListImpl<TI>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
typedef GCONT ListNode<TI> LNode;
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// -- ACCESS
|
|
Packit |
df99a1 |
/** Returns the number of elements in the list. */
|
|
Packit |
df99a1 |
int size() const
|
|
Packit |
df99a1 |
{ return this->nelem; }
|
|
Packit |
df99a1 |
/** Returns the first position in the list. See \Ref{GPosition}. */
|
|
Packit |
df99a1 |
GPosition firstpos() const
|
|
Packit |
df99a1 |
{ return GListImpl<TI>::firstpos(); }
|
|
Packit |
df99a1 |
/** Returns the last position in the list. See \Ref{GPosition}. */
|
|
Packit |
df99a1 |
GPosition lastpos() const
|
|
Packit |
df99a1 |
{ return GListImpl<TI>::lastpos(); }
|
|
Packit |
df99a1 |
/** Implicit notation for GList::firstpos(). */
|
|
Packit |
df99a1 |
operator GPosition() const
|
|
Packit |
df99a1 |
{ return firstpos(); }
|
|
Packit |
df99a1 |
/** Returns a reference to the list element at position #pos#. This
|
|
Packit |
df99a1 |
reference can be used for both reading (as "#a[n]#") and modifying (as
|
|
Packit |
df99a1 |
"#a[n]=v#") a list element. Using an invalid position will cause a
|
|
Packit |
df99a1 |
segmentation violation. See \Ref{GPosition} for efficient operations on
|
|
Packit |
df99a1 |
positions. */
|
|
Packit |
df99a1 |
TYPE& operator[](GPosition pos)
|
|
Packit |
df99a1 |
{ return (TYPE&) (((LNode *)pos.check((void*)this))->val); }
|
|
Packit |
df99a1 |
/** Returns a constant reference to the list element at position #pos#.
|
|
Packit |
df99a1 |
This reference only be used for reading a list element. An exception
|
|
Packit |
df99a1 |
\Ref{GException} is thrown if #pos# is not a valid position. This
|
|
Packit |
df99a1 |
variant of #operator[]# is necessary when dealing with a #const
|
|
Packit |
df99a1 |
GList<TYPE>#. See \Ref{GPosition} for efficient operations on
|
|
Packit |
df99a1 |
positions. */
|
|
Packit |
df99a1 |
const TYPE& operator[](GPosition pos) const
|
|
Packit |
df99a1 |
{ return (const TYPE&) (((const LNode *)pos.check((void*)this))->val); }
|
|
Packit |
df99a1 |
// -- TEST
|
|
Packit |
df99a1 |
/** Tests whether a list is empty.
|
|
Packit |
df99a1 |
Returns a non zero value if the list contains no elements. */
|
|
Packit |
df99a1 |
bool isempty() const
|
|
Packit |
df99a1 |
{ return this->nelem==0; }
|
|
Packit |
df99a1 |
/** Compares two lists. Returns a non zero value if and only if both lists
|
|
Packit |
df99a1 |
contain the same elements (as tested by #TYPE::operator==(const TYPE&)#
|
|
Packit |
df99a1 |
in the same order. */
|
|
Packit |
df99a1 |
int operator==(const GListTemplate<TYPE,TI> &l2) const
|
|
Packit |
df99a1 |
{ return GListImpl<TI>::operator==(l2); }
|
|
Packit |
df99a1 |
// -- SEARCHING
|
|
Packit |
df99a1 |
/** Returns the position #pos# of the #n#-th list element. An invalid
|
|
Packit |
df99a1 |
position is returned if the list contains less than #n# elements. The
|
|
Packit |
df99a1 |
operation works by sequentially scanning the list until reaching the
|
|
Packit |
df99a1 |
#n#-th element. */
|
|
Packit |
df99a1 |
GPosition nth(unsigned int n) const
|
|
Packit |
df99a1 |
{ return GListImpl<TI>::nth(n); }
|
|
Packit |
df99a1 |
/* Compatibility */
|
|
Packit |
df99a1 |
int nth(unsigned int n, GPosition &pos) const
|
|
Packit |
df99a1 |
{ GPosition npos=nth(n); if (npos) pos=npos; return !!pos; }
|
|
Packit |
df99a1 |
/** Tests whether the list contains a given element. If the list contains
|
|
Packit |
df99a1 |
#elt#, the position of the the first list element equal to #elt# as
|
|
Packit |
df99a1 |
checked by #TYPE::operator==(const TYPE&)# is returned. Otherwise an
|
|
Packit |
df99a1 |
invalid position is returned. */
|
|
Packit |
df99a1 |
GPosition contains(const TYPE &elt) const
|
|
Packit |
df99a1 |
{ GPosition pos; GListImpl<TI>::search((const TI&)elt, pos); return pos; }
|
|
Packit |
df99a1 |
/** Searches the list for a given element. If position #pos# is a valid
|
|
Packit |
df99a1 |
position for this list, the search starts at the specified position. If
|
|
Packit |
df99a1 |
position #pos# is not a valid position, the search starts at the
|
|
Packit |
df99a1 |
beginning of the list. The list elements are sequentially compared with
|
|
Packit |
df99a1 |
#elt# using #TYPE::operator==(const TYPE&)#. As soon as a list element
|
|
Packit |
df99a1 |
is equal to #elt#, function #search# sets argument #pos# with the
|
|
Packit |
df99a1 |
position of this list element and returns 1. If however the search
|
|
Packit |
df99a1 |
reaches the end of the list, function #search# returns 0 and leaves
|
|
Packit |
df99a1 |
#pos# unchanged. */
|
|
Packit |
df99a1 |
int search(const TYPE &elt, GPosition &pos) const
|
|
Packit |
df99a1 |
{ return GListImpl<TI>::search((const TI&)elt, pos); }
|
|
Packit |
df99a1 |
// -- ALTERATION
|
|
Packit |
df99a1 |
/** Erases the list contents. All list elements are destroyed and
|
|
Packit |
df99a1 |
unlinked. The list is left with zero elements. */
|
|
Packit |
df99a1 |
void empty()
|
|
Packit |
df99a1 |
{ GListImpl<TI>::empty(); }
|
|
Packit |
df99a1 |
/** Inserts an element after the last element of the list.
|
|
Packit |
df99a1 |
The new element is initialized with a copy of argument #elt#. */
|
|
Packit |
df99a1 |
void append(const TYPE &elt)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::append(this->newnode((const TI&)elt)); }
|
|
Packit |
df99a1 |
/** Inserts an element before the first element of the list.
|
|
Packit |
df99a1 |
The new element is initialized with a copy of argument #elt#. */
|
|
Packit |
df99a1 |
void prepend(const TYPE &elt)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::prepend(this->newnode((const TI&)elt)); }
|
|
Packit |
df99a1 |
/** Inserts a new element after the list element at position #pos#. When
|
|
Packit |
df99a1 |
position #pos# is null the element is inserted at the beginning of the
|
|
Packit |
df99a1 |
list. The new element is initialized with a copy of #elt#. */
|
|
Packit |
df99a1 |
void insert_after(GPosition pos, const TYPE &elt)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::insert_after(pos, this->newnode((const TI&)elt)); }
|
|
Packit |
df99a1 |
/** Inserts a new element before the list element at position #pos#. When
|
|
Packit |
df99a1 |
position #pos# is null the element is inserted at the end of the
|
|
Packit |
df99a1 |
list. The new element is initialized with a copy of #elt#. */
|
|
Packit |
df99a1 |
void insert_before(GPosition pos, const TYPE &elt)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::insert_before(pos, this->newnode((const TI&)elt)); }
|
|
Packit |
df99a1 |
/** Inserts an element of another list into this list. This function
|
|
Packit |
df99a1 |
removes the element at position #frompos# in list #frompos#, inserts it
|
|
Packit |
df99a1 |
in the current list before the element at position #pos#, and advances
|
|
Packit |
df99a1 |
#frompos# to the next element in list #fromlist#. When position #pos# is
|
|
Packit |
df99a1 |
null the element is inserted at the end of the list. */
|
|
Packit |
df99a1 |
void insert_before(GPosition pos, GListTemplate<TYPE,TI> &fromlist, GPosition &frompos)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::insert_before(pos, fromlist, frompos); }
|
|
Packit |
df99a1 |
/** Destroys the list element at position #pos#. This function does
|
|
Packit |
df99a1 |
nothing unless position #pos# is a valid position. */
|
|
Packit |
df99a1 |
void del(GPosition &pos)
|
|
Packit |
df99a1 |
{ GListImpl<TI>::del(pos); }
|
|
Packit |
df99a1 |
/* Old iterators. Do not use. */
|
|
Packit |
df99a1 |
#if GCONTAINER_OLD_ITERATORS
|
|
Packit |
df99a1 |
void first(GPosition &pos) const { pos = firstpos(); }
|
|
Packit |
df99a1 |
void last(GPosition &pos) const { pos = lastpos(); }
|
|
Packit |
df99a1 |
const TYPE *next(GPosition &pos) const
|
|
Packit |
df99a1 |
{ if (!pos) return 0; const TYPE *x=&((*this)[pos]); ++pos; return x; }
|
|
Packit |
df99a1 |
const TYPE *prev(GPosition &pos) const
|
|
Packit |
df99a1 |
{ if (!pos) return 0; const TYPE *x=&((*this)[pos]); --pos; return x; }
|
|
Packit |
df99a1 |
TYPE *next(GPosition &pos)
|
|
Packit |
df99a1 |
{ if (!pos) return 0; TYPE *x=&((*this)[pos]); ++pos; return x; }
|
|
Packit |
df99a1 |
TYPE *prev(GPosition &pos)
|
|
Packit |
df99a1 |
{ if (!pos) return 0; TYPE *x=&((*this)[pos]); --pos; return x; }
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Doubly linked lists. Template class #GList<TYPE># implements a doubly
|
|
Packit |
df99a1 |
linked list of elements of type #TYPE#. This class only implement
|
|
Packit |
df99a1 |
constructors. See class \Ref{GListTemplate} and \Ref{GPosition} for a
|
|
Packit |
df99a1 |
description of all access methods. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class TYPE>
|
|
Packit |
df99a1 |
class GList : public GListTemplate<TYPE,TYPE>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
/** Null Constructor. Constructs a list with zero elements. */
|
|
Packit |
df99a1 |
GList() : GListTemplate<TYPE,TYPE>() {}
|
|
Packit |
df99a1 |
GList& operator=(const GList &r)
|
|
Packit |
df99a1 |
{ GListBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Doubly linked lists for smart pointers.
|
|
Packit |
df99a1 |
Template class #GList<TYPE># implements a doubly linked list of elements
|
|
Packit |
df99a1 |
of type #GP<TYPE># (see \Ref{GSmartPointer.h}). Significantly smaller
|
|
Packit |
df99a1 |
code sizes can be achieved by using this class instead of the more general
|
|
Packit |
df99a1 |
#GArray<GP<TYPE>>#.
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GListTemplate} and
|
|
Packit |
df99a1 |
\Ref{GPosition} for a description of all access methods. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class TYPE>
|
|
Packit |
df99a1 |
class GPList : public GListTemplate<GP<TYPE>,GPBase>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
/** Null Constructor. Constructs a list with zero elements. */
|
|
Packit |
df99a1 |
GPList() : GListTemplate<GP<TYPE>,GPBase>() {}
|
|
Packit |
df99a1 |
GPList& operator=(const GPList &r)
|
|
Packit |
df99a1 |
{ GListBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
// ASSOCIATIVE MAPS
|
|
Packit |
df99a1 |
// ------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name Associative Maps
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
These template classes implements a associative maps. The associative map
|
|
Packit |
df99a1 |
contains an arbitrary number of entries. Each entry is a pair containing
|
|
Packit |
df99a1 |
one element of type #KTYPE# (named the "key") and one element of type
|
|
Packit |
df99a1 |
#VTYPE# (named the "value"). All entries have distinct keys.
|
|
Packit |
df99a1 |
These template class must be able to access the following functions:
|
|
Packit |
df99a1 |
\begin{itemize}
|
|
Packit |
df99a1 |
\item a #VTYPE# default constructor #VTYPE::VTYPE()#,
|
|
Packit |
df99a1 |
\item a #VTYPE# copy constructor #VTYPE::VTYPE(const VTYPE &)#,
|
|
Packit |
df99a1 |
\item optionally a #VTYPE# destructor #VTYPE::~VTYPE()#,
|
|
Packit |
df99a1 |
\item a #KTYPE# default constructor #KTYPE::KTYPE()#,
|
|
Packit |
df99a1 |
\item a #KTYPE# copy constructor #KTYPE::KTYPE(const KTYPE &)#,
|
|
Packit |
df99a1 |
\item optionally a #KTYPE# destructor #KTYPE::~KTYPE()#,
|
|
Packit |
df99a1 |
\item a #KTYPE# comparison operator #KTYPE::operator==(const KTYPE &)#,
|
|
Packit |
df99a1 |
\item and a #KTYPE# hashing function #hash(const KTYPE&)#.
|
|
Packit |
df99a1 |
\end{itemize}
|
|
Packit |
df99a1 |
The hashing function must return an #unsigned int# number. Multiple
|
|
Packit |
df99a1 |
invocations of the hashing function with equal arguments (in the sense of
|
|
Packit |
df99a1 |
#KTYPE::operator==#) must always return the same number.
|
|
Packit |
df99a1 |
Position objects (see \Ref{GPosition}) may be used to iterate over the
|
|
Packit |
df99a1 |
entries contained by an associative map.
|
|
Packit |
df99a1 |
@memo Associative maps.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI GSetBase : public GCont
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GSetBase(const Traits &traits);
|
|
Packit |
df99a1 |
GSetBase(const GSetBase &ref;;
|
|
Packit |
df99a1 |
static GCONT HNode *newnode(const void *key);
|
|
Packit |
df99a1 |
HNode *hashnode(unsigned int hashcode) const;
|
|
Packit |
df99a1 |
HNode *installnode(HNode *n);
|
|
Packit |
df99a1 |
void deletenode(HNode *n);
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
const Traits &traits;
|
|
Packit |
df99a1 |
int nelems;
|
|
Packit |
df99a1 |
int nbuckets;
|
|
Packit |
df99a1 |
HNode **table;
|
|
Packit |
df99a1 |
GPBuffer<HNode *> gtable;
|
|
Packit |
df99a1 |
HNode *first;
|
|
Packit |
df99a1 |
private:
|
|
Packit |
df99a1 |
void insertnode(HNode *n);
|
|
Packit |
df99a1 |
void rehash(int newbuckets);
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
~GSetBase();
|
|
Packit |
df99a1 |
GSetBase& operator=(const GSetBase &ref;;
|
|
Packit |
df99a1 |
GPosition firstpos() const;
|
|
Packit |
df99a1 |
void del(GPosition &pos;;
|
|
Packit |
df99a1 |
void empty();
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class K>
|
|
Packit |
df99a1 |
class GSetImpl : public GSetBase
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
typedef GCONT SetNode<K> SNode;
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GSetImpl();
|
|
Packit |
df99a1 |
GSetImpl(const Traits &traits);
|
|
Packit |
df99a1 |
HNode *get(const K &key) const;
|
|
Packit |
df99a1 |
HNode *get_or_throw(const K &key) const;
|
|
Packit |
df99a1 |
HNode *get_or_create(const K &key);
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
GPosition contains(const K &key) const
|
|
Packit |
df99a1 |
{ return GPosition( get(key), (void*)this); }
|
|
Packit |
df99a1 |
void del(const K &key)
|
|
Packit |
df99a1 |
{ deletenode(get(key)); }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K>
|
|
Packit |
df99a1 |
GSetImpl<K>::GSetImpl()
|
|
Packit |
df99a1 |
: GSetBase( GCONT NormTraits<GCONT SetNode<K> >::traits() )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K>
|
|
Packit |
df99a1 |
GSetImpl<K>::GSetImpl(const Traits &traits)
|
|
Packit |
df99a1 |
: GSetBase(traits)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K> GCONT HNode *
|
|
Packit |
df99a1 |
GSetImpl<K>::get(const K &key) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
unsigned int hashcode = hash(key);
|
|
Packit |
df99a1 |
for (SNode *s=(SNode*)hashnode(hashcode); s; s=(SNode*)(s->hprev))
|
|
Packit |
df99a1 |
if (s->hashcode == hashcode && s->key == key) return s;
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#if GCONTAINER_BOUNDS_CHECK
|
|
Packit |
df99a1 |
template<class K> GCONT HNode *
|
|
Packit |
df99a1 |
GSetImpl<K>::get_or_throw(const K &key) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
HNode *m = get(key);
|
|
Packit |
df99a1 |
if (!m)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("GContainer.cannot_add") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return m;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
template<class K> inline GCONT HNode *
|
|
Packit |
df99a1 |
GSetImpl<K>::get_or_throw(const K &key) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return get(key);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K> GCONT HNode *
|
|
Packit |
df99a1 |
GSetImpl<K>::get_or_create(const K &key)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
HNode *m = get(key);
|
|
Packit |
df99a1 |
if (m) return m;
|
|
Packit |
df99a1 |
SNode *n = (SNode*) operator new (sizeof(SNode));
|
|
Packit |
df99a1 |
#if GCONTAINER_ZERO_FILL
|
|
Packit |
df99a1 |
memset(n, 0, sizeof(SNode));
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
new ((void*)&(n->key)) K ( key );
|
|
Packit |
df99a1 |
n->hashcode = hash((const K&)(n->key));
|
|
Packit |
df99a1 |
installnode(n);
|
|
Packit |
df99a1 |
return n;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class K, class TI>
|
|
Packit |
df99a1 |
class GMapImpl : public GSetImpl<K>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
typedef GCONT MapNode<K,TI> MNode;
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GMapImpl();
|
|
Packit |
df99a1 |
GMapImpl(const GCONT Traits &traits);
|
|
Packit |
df99a1 |
GCONT HNode* get_or_create(const K &key);
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K, class TI>
|
|
Packit |
df99a1 |
GMapImpl<K,TI>::GMapImpl()
|
|
Packit |
df99a1 |
: GSetImpl<K> ( GCONT NormTraits<GCONT MapNode<K,TI> >::traits() )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K, class TI>
|
|
Packit |
df99a1 |
GMapImpl<K,TI>::GMapImpl(const GCONT Traits &traits)
|
|
Packit |
df99a1 |
: GSetImpl<K>(traits)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template<class K, class TI> GCONT HNode *
|
|
Packit |
df99a1 |
GMapImpl<K,TI>::get_or_create(const K &key)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GCONT HNode *m = this->get(key);
|
|
Packit |
df99a1 |
if (m) return m;
|
|
Packit |
df99a1 |
MNode *n = (MNode*) operator new (sizeof(MNode));
|
|
Packit |
df99a1 |
#if GCONTAINER_ZERO_FILL
|
|
Packit |
df99a1 |
memset(n, 0, sizeof(MNode));
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
new ((void*)&(n->key)) K (key);
|
|
Packit |
df99a1 |
new ((void*)&(n->val)) TI ();
|
|
Packit |
df99a1 |
n->hashcode = hash((const K&)(n->key));
|
|
Packit |
df99a1 |
this->installnode(n);
|
|
Packit |
df99a1 |
return n;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Common base class for all associative maps.
|
|
Packit |
df99a1 |
Class \Ref{GArrayTemplate} implements all methods for manipulating
|
|
Packit |
df99a1 |
associative maps with key type #KTYPE# and value type #VTYPE#.
|
|
Packit |
df99a1 |
You should not however create instances of this class.
|
|
Packit |
df99a1 |
You should instead use class \Ref{GMap} or \Ref{GPMap}. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class KTYPE, class VTYPE, class TI>
|
|
Packit |
df99a1 |
class GMapTemplate : protected GMapImpl<KTYPE,TI>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
typedef GCONT MapNode<KTYPE,TI> MNode;
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
/** Returns the number of elements in the map. */
|
|
Packit |
df99a1 |
int size() const
|
|
Packit |
df99a1 |
{ return this->nelems; }
|
|
Packit |
df99a1 |
/** Returns the first position in the map. */
|
|
Packit |
df99a1 |
GPosition firstpos() const
|
|
Packit |
df99a1 |
{ return GMapImpl<KTYPE,TI>::firstpos(); }
|
|
Packit |
df99a1 |
/** Implicit notation for GMap::firstpos(). */
|
|
Packit |
df99a1 |
operator GPosition() const
|
|
Packit |
df99a1 |
{ return firstpos(); }
|
|
Packit |
df99a1 |
/** Tests whether the associative map is empty.
|
|
Packit |
df99a1 |
Returns a non zero value if and only if the map contains zero entries. */
|
|
Packit |
df99a1 |
bool isempty() const
|
|
Packit |
df99a1 |
{ return this->nelems==0; }
|
|
Packit |
df99a1 |
/** Searches an entry for key #key#. If the map contains an entry whose key
|
|
Packit |
df99a1 |
is equal to #key# according to #KTYPE::operator==(const KTYPE&)#, this
|
|
Packit |
df99a1 |
function returns its position. Otherwise it returns an invalid
|
|
Packit |
df99a1 |
position. */
|
|
Packit |
df99a1 |
GPosition contains(const KTYPE &key) const
|
|
Packit |
df99a1 |
{ return GMapImpl<KTYPE,TI>::contains(key); }
|
|
Packit |
df99a1 |
/* Compatibility */
|
|
Packit |
df99a1 |
GPosition contains(const KTYPE &key, GPosition &pos) const
|
|
Packit |
df99a1 |
{ return pos = GMapImpl<KTYPE,TI>::contains(key); }
|
|
Packit |
df99a1 |
// -- ALTERATION
|
|
Packit |
df99a1 |
/** Erases the associative map contents. All entries are destroyed and
|
|
Packit |
df99a1 |
removed. The map is left with zero entries. */
|
|
Packit |
df99a1 |
void empty()
|
|
Packit |
df99a1 |
{ GMapImpl<KTYPE,TI>::empty(); }
|
|
Packit |
df99a1 |
/** Returns a constant reference to the key of the map entry at position
|
|
Packit |
df99a1 |
#pos#. An exception \Ref{GException} is thrown if position #pos# is not
|
|
Packit |
df99a1 |
valid. There is no direct way to change the key of a map entry. */
|
|
Packit |
df99a1 |
const KTYPE &key(const GPosition &pos) const
|
|
Packit |
df99a1 |
{ return (const KTYPE&)(((MNode*)(pos.check((void*)this)))->key); }
|
|
Packit |
df99a1 |
/** Returns a reference to the value of the map entry at position #pos#.
|
|
Packit |
df99a1 |
This reference can be used for both reading (as "#a[n]#") and modifying
|
|
Packit |
df99a1 |
(as "#a[n]=v#"). An exception \Ref{GException} is thrown if position
|
|
Packit |
df99a1 |
#pos# is not valid. */
|
|
Packit |
df99a1 |
VTYPE& operator[](const GPosition &pos)
|
|
Packit |
df99a1 |
{ return (VTYPE&)(((MNode*)(pos.check((void*)this)))->val); }
|
|
Packit |
df99a1 |
/** Returns a constant reference to the value of the map entry at position
|
|
Packit |
df99a1 |
#pos#. This reference can only be used for reading (as "#a[n]#") the
|
|
Packit |
df99a1 |
entry value. An exception \Ref{GException} is thrown if position #pos#
|
|
Packit |
df99a1 |
is not valid. */
|
|
Packit |
df99a1 |
const VTYPE& operator[](const GPosition &pos) const
|
|
Packit |
df99a1 |
{ return (const VTYPE&)(((MNode*)(pos.check((void*)this)))->val); }
|
|
Packit |
df99a1 |
/** Returns a constant reference to the value of the map entry for key
|
|
Packit |
df99a1 |
#key#. This reference can only be used for reading (as "#a[n]#") the
|
|
Packit |
df99a1 |
entry value. An exception \Ref{GException} is thrown if no entry
|
|
Packit |
df99a1 |
contains key #key#. This variant of #operator[]# is necessary when
|
|
Packit |
df99a1 |
dealing with a #const GMAP<KTYPE,VTYPE>#. */
|
|
Packit |
df99a1 |
const VTYPE& operator[](const KTYPE &key) const
|
|
Packit |
df99a1 |
{ return (const VTYPE&)(((const MNode*)(this->get_or_throw(key)))->val); }
|
|
Packit |
df99a1 |
/** Returns a reference to the value of the map entry for key #key#. This
|
|
Packit |
df99a1 |
reference can be used for both reading (as "#a[n]#") and modifying (as
|
|
Packit |
df99a1 |
"#a[n]=v#"). If there is no entry for key #key#, a new entry is created
|
|
Packit |
df99a1 |
for that key with the null constructor #VTYPE::VTYPE()#. */
|
|
Packit |
df99a1 |
VTYPE& operator[](const KTYPE &key)
|
|
Packit |
df99a1 |
{ return (VTYPE&)(((MNode*)(this->get_or_create(key)))->val); }
|
|
Packit |
df99a1 |
/** Destroys the map entry for position #pos#.
|
|
Packit |
df99a1 |
Nothing is done if position #pos# is not a valid position. */
|
|
Packit |
df99a1 |
void del(GPosition &pos)
|
|
Packit |
df99a1 |
{ GSetBase::del(pos); }
|
|
Packit |
df99a1 |
/** Destroys the map entry for key #key#.
|
|
Packit |
df99a1 |
Nothing is done if there is no entry for key #key#. */
|
|
Packit |
df99a1 |
void del(const KTYPE &key)
|
|
Packit |
df99a1 |
{ GMapImpl<KTYPE,TI>::del(key); }
|
|
Packit |
df99a1 |
/* Old iterators. Do not use. */
|
|
Packit |
df99a1 |
#if GCONTAINER_OLD_ITERATORS
|
|
Packit |
df99a1 |
void first(GPosition &pos) const { pos = firstpos(); }
|
|
Packit |
df99a1 |
const VTYPE *next(GPosition &pos) const
|
|
Packit |
df99a1 |
{ if (!pos) return 0; const VTYPE *x=&((*this)[pos]); ++pos; return x; }
|
|
Packit |
df99a1 |
VTYPE *next(GPosition &pos)
|
|
Packit |
df99a1 |
{ if (!pos) return 0; VTYPE *x=&((*this)[pos]); ++pos; return x; }
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Associative maps.
|
|
Packit |
df99a1 |
Template class #GMap<KTYPE,VTYPE># implements an associative map.
|
|
Packit |
df99a1 |
The map contains an arbitrary number of entries. Each entry is a
|
|
Packit |
df99a1 |
pair containing one element of type #KTYPE# (named the "key") and one
|
|
Packit |
df99a1 |
element of type #VTYPE# (named the "value").
|
|
Packit |
df99a1 |
The entry associated to a particular value of the key can retrieved
|
|
Packit |
df99a1 |
very efficiently.
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GMapTemplate} and
|
|
Packit |
df99a1 |
\Ref{GPosition} for a description of all access methods.*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class KTYPE, class VTYPE>
|
|
Packit |
df99a1 |
class GMap : public GMapTemplate<KTYPE,VTYPE,VTYPE>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// -- ACCESS
|
|
Packit |
df99a1 |
GMap() : GMapTemplate<KTYPE,VTYPE,VTYPE>() {}
|
|
Packit |
df99a1 |
GMap& operator=(const GMap &r)
|
|
Packit |
df99a1 |
{ GSetBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Associative maps for smart-pointers.
|
|
Packit |
df99a1 |
Template class #GMap<KTYPE,VTYPE># implements an associative map for key
|
|
Packit |
df99a1 |
type #KTYPE# and value type #GP<VTYPE># (see \Ref{GSmartPointer.h}). The
|
|
Packit |
df99a1 |
map contains an arbitrary number of entries. Each entry is a pair
|
|
Packit |
df99a1 |
containing one element of type #KTYPE# (named the "key") and one aelement
|
|
Packit |
df99a1 |
of type #VTYPE# (named the "value"). The entry associated to a particular
|
|
Packit |
df99a1 |
value of the key can retrieved very efficiently.
|
|
Packit |
df99a1 |
Significantly smaller code sizes can be achieved by using this class
|
|
Packit |
df99a1 |
instead of the more general #GMap<KTYPE,GP<VTYPE>># (see \Ref{GMap}).
|
|
Packit |
df99a1 |
This class only implement constructors. See class \Ref{GMapTemplate} and
|
|
Packit |
df99a1 |
\Ref{GPosition} for a description of all access methods.*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
template <class KTYPE, class VTYPE>
|
|
Packit |
df99a1 |
class GPMap : public GMapTemplate<KTYPE,GP<VTYPE>,GPBase>
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
GPMap() : GMapTemplate<KTYPE,GP<VTYPE>,GPBase>() {}
|
|
Packit |
df99a1 |
GPMap& operator=(const GPMap &r)
|
|
Packit |
df99a1 |
{ GSetBase::operator=(r); return *this; }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ------------ THE END
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef HAVE_NAMESPACES
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
# ifndef NOT_USING_DJVU_NAMESPACE
|
|
Packit |
df99a1 |
using namespace DJVU;
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|