1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
|
//C- -------------------------------------------------------------------
//C- DjVuLibre-3.5
//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
//C- Copyright (c) 2001 AT&T
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, Version 2. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- This program is distributed in the hope that it will be useful,
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//C- GNU General Public License for more details.
//C-
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech
//C- Software authorized us to replace the original DjVu(r) Reference
//C- Library notice by the following text (see doc/lizard2002.djvu):
//C-
//C- ------------------------------------------------------------------
//C- | DjVu (r) Reference Library (v. 3.5)
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
//C- | 6,058,214 and patents pending.
//C- |
//C- | This software is subject to, and may be distributed under, the
//C- | GNU General Public License, Version 2. The license should have
//C- | accompanied the software or you may obtain a copy of the license
//C- | from the Free Software Foundation at http://www.fsf.org .
//C- |
//C- | The computer code originally released by LizardTech under this
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
//C- | ORIGINAL CODE." Subject to any third party intellectual property
//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
//C- | non-exclusive license to make, use, sell, or otherwise dispose of
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
//C- | General Public License. This grant only confers the right to
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
//C- | the extent such infringement is reasonably necessary to enable
//C- | recipient to make, have made, practice, sell, or otherwise dispose
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
//C- | any greater extent that may be necessary to utilize further
//C- | modifications or combinations.
//C- |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C- +------------------------------------------------------------------
//
// $Id: Arrays.h,v 1.10 2004/05/13 15:16:34 leonb Exp $
// $Name: release_3_5_15 $
#ifndef _ARRAYS_H_
#define _ARRAYS_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma interface
#endif
#include "GException.h"
#include "GSmartPointer.h"
#include <string.h>
#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif
/** @name Arrays.h
Files #"Arrays.h"# and #"Arrays.cpp"# implement three array template classes.
Class \Ref{TArray} implements an array of objects of trivial types
such as #char#, #int#, #float#, etc. It is faster than general implementation
for any type done in \Ref{DArray} because it does not cope with
element's constructors, destructors and copy operators. Although
implemented as a template, which makes it possible to incorrectly use
\Ref{TArray} with non-trivial classes, it should not be done.
A lot of things is shared by these three arrays. That is why there are
more base classes:
\begin{itemize}
\item \Ref{ArrayBase} defines functions independent of the elements type
\item \Ref{ArrayBaseT} template class defining functions shared by
\Ref{DArray} and \Ref{TArray}
\end{itemize}
The main difference between \Ref{GArray} (now obsolete) and these ones
is the copy-on-demand strategy, which allows you to copy array objects
without copying the real data. It's the same thing, which has been
implemented in \Ref{GString} long ago: as long as you don't try to modify
the underlying data, it may be shared between several copies of array
objects. As soon as you attempt to make any changes, a private copy
is created automatically and transparently for you - the procedure, that
we call "copy-on-demand".
Also, please note that now there is no separate class, which does fast
sorting. Both \Ref{TArray} (dynamic array for trivial types) and
\Ref{DArray} (dynamic array for arbitrary types) can sort their elements.
{\bf Historical comments} --- Leon chose to implement his own arrays because
the STL classes were not universally available and the compilers were
rarely able to deal with such a template galore. Later it became clear
that there is no really good reason why arrays should be derived from
containers. It was also suggested to create separate arrays implementation
for simple classes and do the copy-on-demand strategy, which would allow
to assign array objects without immediate copying of their elements.
At this point \Ref{DArray} and \Ref{TArray} should only be used when
it is critical to have the copy-on-demand feature. The \Ref{GArray}
implementation is a lot more efficient.
@memo Template array classes.
@author
Andrei Erofeev <[email protected]> -- Copy-on-demand implementation.
@version
#$Id: Arrays.h,v 1.10 2004/05/13 15:16:34 leonb Exp $# */
//@{
// Auxiliary classes: Will be used in place of GPBase and GPEnabled objects
class _ArrayRep
{
friend class _ArrayBase;
public:
_ArrayRep(void) : count(0) {}
_ArrayRep(const _ArrayRep &) {}
virtual ~_ArrayRep(void) {}
_ArrayRep & operator=(const _ArrayRep &) { return *this; }
int get_count(void) const { return count; }
private:
int count;
void ref(void) { count++; }
void unref(void) { if (--count==0) delete this; }
};
class _ArrayBase
{
public:
_ArrayBase(void) : rep(0) {}
_ArrayBase(const _ArrayBase & ab) : rep(0)
{
if (ab.rep) ab.rep->ref();
rep=ab.rep;
}
_ArrayBase(_ArrayRep * ar) : rep(0)
{
if (ar) ar->ref();
rep=ar;
}
virtual ~_ArrayBase(void)
{
if (rep) { rep->unref(); rep=0; }
}
_ArrayRep * get(void) const { return rep; }
_ArrayBase & assign(_ArrayRep * ar)
{
if (ar) ar->ref();
if (rep) rep->unref();
rep=ar;
return *this;
}
_ArrayBase & operator=(const _ArrayBase & ab) { return assign(ab.rep); }
bool operator==(const _ArrayBase & ab) { return rep==ab.rep; }
private:
_ArrayRep * rep;
};
// Internal "Array repository" holding the pointer to the actual data,
// data bounds, etc. It copes with data elements with the help of five
// static functions which pointers are supposed to be passed to the
// constructor.
class ArrayRep : public _ArrayRep
{
public:
ArrayRep(int elsize,
void (* xdestroy)(void *, int, int),
void (* xinit1)(void *, int, int),
void (* xinit2)(void *, int, int, const void *, int, int),
void (* xcopy)(void *, int, int, const void *, int, int),
void (* xinsert)(void *, int, int, const void *, int));
ArrayRep(int elsize,
void (* xdestroy)(void *, int, int),
void (* xinit1)(void *, int, int),
void (* xinit2)(void *, int, int, const void *, int, int),
void (* xcopy)(void *, int, int, const void *, int, int),
void (* xinsert)(void *, int, int, const void *, int),
int hibound);
ArrayRep(int elsize,
void (* xdestroy)(void *, int, int),
void (* xinit1)(void *, int, int),
void (* xinit2)(void *, int, int, const void *, int, int),
void (* xcopy)(void *, int, int, const void *, int, int),
void (* xinsert)(void *, int, int, const void *, int),
int lobound, int hibound);
ArrayRep(const ArrayRep & rep);
virtual ~ArrayRep();
// Following is the standard interface to DArray. DArray will call these
// functions to access data.
int size() const;
int lbound() const;
int hbound() const;
void empty();
void touch(int n);
void resize(int lobound, int hibound);
void shift(int disp);
void del(int n, unsigned int howmany=1);
// ins() is an exception. It does it job only partially.
// The derived class is supposed to finish insertion.
void ins(int n, const void * what, unsigned int howmany);
ArrayRep & operator=(const ArrayRep & rep);
// All data is public because DArray... classes will need access to it
void *data;
int minlo;
int maxhi;
int lobound;
int hibound;
int elsize;
private:
// These functions can't be virtual as they're called from
// constructors and destructors :((
// destroy(): should destroy elements in data[] array from 'lo' to 'hi'
void (* destroy)(void * data, int lo, int hi);
// init1(): should initialize elements in data[] from 'lo' to 'hi'
// using default constructors
void (* init1)(void * data, int lo, int hi);
// init2(): should initialize elements in data[] from 'lo' to 'hi'
// using corresponding elements from src[] (copy constructor)
void (* init2)(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi);
// copy(): should copy elements from src[] to dst[] (copy operator)
void (* copy)(void * dst, int dst_lo, int dst_hi,
const void * src, int src_lo, int src_hi);
// insert(): should insert '*what' at position 'where' 'howmany' times
// into array data[] having 'els' initialized elements
void (* insert)(void * data, int els, int where, const void * what,
int howmany);
};
inline int
ArrayRep::size() const
{
return hibound - lobound + 1;
}
inline int
ArrayRep::lbound() const
{
return lobound;
}
inline int
ArrayRep::hbound() const
{
return hibound;
}
inline void
ArrayRep::empty()
{
resize(0, -1);
}
inline void
ArrayRep::touch(int n)
{
if (hibound < lobound)
{
resize(n,n);
} else
{
int nlo = lobound;
int nhi = hibound;
if (n < nlo) nlo = n;
if (n > nhi) nhi = n;
resize(nlo, nhi);
}
}
/** Dynamic array base class.
This is an auxiliary base class for \Ref{DArray} and \Ref{TArray}
implementing some shared functions independent of the type of array
elements. It's not supposed to be constructed by hands. Use \Ref{DArray}
and \Ref{TArray} instead.
*/
class ArrayBase : protected _ArrayBase
{
protected:
void check(void);
void detach(void);
ArrayBase(void) {};
public:
/// Returns the number of elements in the array
int size() const;
/** Returns the lower bound of the valid subscript range. */
int lbound() const;
/** Returns the upper bound of the valid subscript range. */
int hbound() const;
/** Erases the array contents. All elements in the array are destroyed.
The valid subscript range is set to the empty range. */
void empty();
/** Extends the subscript range so that is contains #n#.
This function does nothing if #n# is already int the valid subscript range.
If the valid range was empty, both the lower bound and the upper bound
are set to #n#. Otherwise the valid subscript range is extended
to encompass #n#. This function is very handy when called before setting
an array element:
\begin{verbatim}
int lineno=1;
DArray<GString> a;
while (! end_of_file()) {
a.touch[lineno];
a[lineno++] = read_a_line();
}
\end{verbatim}
*/
void touch(int n);
/** Resets the valid subscript range to #0#---#hibound#.
This function may destroy some array elements and may construct
new array elements with the null constructor. Setting #hibound# to
#-1# resets the valid subscript range to the empty range.
@param hibound upper bound of the new subscript range. */
void resize(int hibound);
/** Resets the valid subscript range to #lobound#---#hibound#.
This function may destroy some array elements and may construct
new array elements with the null constructor. Setting #lobound# to #0# and
#hibound# to #-1# resets the valid subscript range to the empty range.
@param lobound lower bound of the new subscript range.
@param hibound upper bound of the new subscript range. */
void resize(int lobound, int hibound);
/** Shifts the valid subscript range. Argument #disp# is added to both
bounds of the valid subscript range. Array elements previously
located at subscript #x# will now be located at subscript #x+disp#. */
void shift(int disp);
/** Deletes array elements. The array elements corresponding to
subscripts #n#...#n+howmany-1# are destroyed. All array elements
previously located at subscripts greater or equal to #n+howmany#
are moved to subscripts starting with #n#. The new subscript upper
bound is reduced in order to account for this shift.
@param n subscript of the first element to delete.
@param howmany number of elements to delete. */
void del(int n, unsigned int howmany=1);
virtual ~ArrayBase(void) {};
};
inline void
ArrayBase::detach(void)
{
ArrayRep * new_rep=new ArrayRep(*(ArrayRep *) get());
assign(new_rep);
}
inline void
ArrayBase::check(void)
{
if (get()->get_count()>1) detach();
}
inline int
ArrayBase::size() const
{
return ((const ArrayRep *) get())->size();
}
inline int
ArrayBase::lbound() const
{
return ((const ArrayRep *) get())->lobound;
}
inline int
ArrayBase::hbound() const
{
return ((const ArrayRep *) get())->hibound;
}
inline void
ArrayBase::empty()
{
check();
((ArrayRep *) get())->empty();
}
inline void
ArrayBase::resize(int lo, int hi)
{
check();
((ArrayRep *) get())->resize(lo, hi);
}
inline void
ArrayBase::resize(int hi)
{
resize(0, hi);
}
inline void
ArrayBase::touch(int n)
{
check();
((ArrayRep *) get())->touch(n);
}
inline void
ArrayBase::shift(int disp)
{
check();
((ArrayRep *) get())->shift(disp);
}
inline void
ArrayBase::del(int n, unsigned int howmany)
{
check();
((ArrayRep *) get())->del(n, howmany);
}
/** Dynamic array template base class.
This is an auxiliary template base class for \Ref{DArray} and \Ref{TArray}
implementing some shared functions which {\em depend} on the type of
the array elements (this is contrary to \Ref{ArrayBase}).
It's not supposed to be constructed by hands. Use \Ref{DArray} and
\Ref{TArray} instead.
*/
template <class TYPE>
class ArrayBaseT : public ArrayBase
{
public:
virtual ~ArrayBaseT(void) {};
/** Returns a reference to the array element for subscript #n#. This
reference can be used for both reading (as "#a[n]#") and writing (as
"#a[n]=v#") an array element. This operation will not extend the valid
subscript range: an exception \Ref{GException} is thrown if argument #n#
is not in the valid subscript range. */
TYPE& operator[](int n);
/** Returns a constant reference to the array element for subscript #n#.
This reference can only be used for reading (as "#a[n]#") an array
element. This operation will not extend the valid subscript range: an
exception \Ref{GException} is thrown if argument #n# is not in the valid
subscript range. This variant of #operator[]# is necessary when dealing
with a #const DArray<TYPE>#. */
const TYPE& operator[](int n) const;
/** Returns a pointer for reading or writing the array elements. This
pointer can be used to access the array elements with the same
subscripts and the usual bracket syntax. This pointer remains valid as
long as the valid subscript range is unchanged. If you change the
subscript range, you must stop using the pointers returned by prior
invocation of this conversion operator. */
operator TYPE* ();
/** Returns a pointer for reading (but not modifying) the array elements.
This pointer can be used to access the array elements with the same
subscripts and the usual bracket syntax. This pointer remains valid as
long as the valid subscript range is unchanged. If you change the
subscript range, you must stop using the pointers returned by prior
invocation of this conversion operator. */
operator const TYPE* () const;
#ifndef __MWERKS__ //MCW can't compile
operator const TYPE* ();
#endif
/** Insert new elements into an array. This function inserts
#howmany# elements at position #n# into the array. The initial value #val#
is copied into the new elements. All array elements previously located at subscripts
#n# and higher are moved to subscripts #n+howmany# and higher. The upper bound of the
valid subscript range is increased in order to account for this shift.
@param n subscript of the first inserted element.
@param val initial value of the new elements.
@param howmany number of elements to insert. */
void ins(int n, const TYPE &val, unsigned int howmany=1);
/** Sort array elements. Sort all array elements in ascending order. Array
elements are compared using the less-or-equal comparison operator for
type #TYPE#. */
void sort();
/** Sort array elements in subscript range #lo# to #hi#. Sort all array
elements whose subscripts are in range #lo#..#hi# in ascending order.
The other elements of the array are left untouched. An exception is
thrown if arguments #lo# and #hi# are not in the valid subscript range.
Array elements are compared using the less-or-equal comparison operator
for type #TYPE#.
@param lo low bound for the subscripts of the elements to sort.
@param hi high bound for the subscripts of the elements to sort. */
void sort(int lo, int hi);
protected:
ArrayBaseT(void) {};
private:
// Callbacks called from ArrayRep
static void destroy(void * data, int lo, int hi);
static void init1(void * data, int lo, int hi);
static void init2(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi);
static void copy(void * dst, int dst_lo, int dst_hi,
const void * src, int src_lo, int src_hi);
static void insert(void * data, int els, int where,
const void * what, int howmany);
};
template <class TYPE> inline
ArrayBaseT<TYPE>::operator TYPE* ()
{
check();
ArrayRep * rep=(ArrayRep *) get();
return &((TYPE *) rep->data)[-rep->minlo];
}
#ifndef __MWERKS__ //MCW can't compile
template <class TYPE> inline
ArrayBaseT<TYPE>::operator const TYPE* ()
{
const ArrayRep * rep=(const ArrayRep *) get();
return &((const TYPE *) rep->data)[-rep->minlo];
}
#endif
template <class TYPE> inline
ArrayBaseT<TYPE>::operator const TYPE* () const
{
const ArrayRep * rep=(const ArrayRep *) get();
return &((const TYPE *) rep->data)[-rep->minlo];
}
template <class TYPE> inline TYPE&
ArrayBaseT<TYPE>::operator[](int n)
{
check();
ArrayRep * rep=(ArrayRep *) get();
if (n<rep->lobound || n>rep->hibound)
G_THROW( ERR_MSG("arrays.ill_sub") );
return ((TYPE *) rep->data)[n - rep->minlo];
}
template <class TYPE> inline const TYPE&
ArrayBaseT<TYPE>::operator[](int n) const
{
const ArrayRep * rep=(const ArrayRep *) get();
if (n<rep->lobound || n>rep->hibound)
G_THROW( ERR_MSG("arrays.ill_sub") );
return ((const TYPE *) rep->data)[n - rep->minlo];
}
template <class TYPE> inline void
ArrayBaseT<TYPE>::ins(int n, const TYPE &val, unsigned int howmany)
{
check();
((ArrayRep *) get())->ins(n, &val, howmany);
}
template <class TYPE> void
ArrayBaseT<TYPE>::sort()
{
sort(lbound(), hbound());
}
template <class TYPE> void
ArrayBaseT<TYPE>::sort(int lo, int hi)
{
if (hi <= lo)
return;
// Test for insertion sort (optimize!)
if (hi <= lo + 20)
{
for (int i=lo+1; i<=hi; i++)
{
int j = i;
TYPE tmp = (*this)[i];
while ((--j>=lo) && !((*this)[j]<=tmp))
(*this)[j+1] = (*this)[j];
(*this)[j+1] = tmp;
}
return;
}
// -- determine suitable quick-sort pivot
TYPE tmp = (*this)[lo];
TYPE pivot = (*this)[(lo+hi)/2];
if (pivot <= tmp)
{ tmp = pivot; pivot=(*this)[lo]; }
if ((*this)[hi] <= tmp)
{ pivot = tmp; }
else if ((*this)[hi] <= pivot)
{ pivot = (*this)[hi]; }
// -- partition set
int h = hi;
int l = lo;
while (l < h)
{
while (! (pivot <= (*this)[l])) l++;
while (! ((*this)[h] <= pivot)) h--;
if (l < h)
{
tmp = (*this)[l];
(*this)[l] = (*this)[h];
(*this)[h] = tmp;
l = l+1;
h = h-1;
}
}
// -- recursively restart
sort(lo, h);
sort(l, hi);
}
/** Dynamic array for simple types.
Template class #TArray<TYPE># implements an array of
elements of {\em simple} type #TYPE#. {\em Simple} means that the type
may be #char#, #int#, #float# etc. The limitation is imposed by the
way in which the #TArray# is working with its elements: it's not trying
to execute elements' constructors, destructors or copy operators. It's
just doing bitwise copy. Except for this it's pretty much the same as
\Ref{DArray}.
Please note that most of the methods are implemented in the base classes
\Ref{ArrayBase} and \Ref{ArrayBaseT}.
*/
template <class TYPE>
class TArray : public ArrayBaseT<TYPE> {
public:
/** Constructs an empty array. The valid subscript range is initially
empty. Member function #touch# and #resize# provide convenient ways
to enlarge the subscript range. */
TArray();
/** Constructs an array with subscripts in range 0 to #hibound#.
The subscript range can be subsequently modified with member functions
#touch# and #resize#.
@param hibound upper bound of the initial subscript range. */
TArray(int hibound);
/** Constructs an array with subscripts in range #lobound# to #hibound#.
The subscript range can be subsequently modified with member functions
#touch# and #resize#.
@param lobound lower bound of the initial subscript range.
@param hibound upper bound of the initial subscript range. */
TArray(int lobound, int hibound);
virtual ~TArray() {};
private:
// Callbacks called from ArrayRep
static void destroy(void * data, int lo, int hi);
static void init1(void * data, int lo, int hi);
static void init2(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi);
static void insert(void * data, int els, int where,
const void * what, int howmany);
};
template <class TYPE> void
TArray<TYPE>::destroy(void * data, int lo, int hi)
{
}
template <class TYPE> void
TArray<TYPE>::init1(void * data, int lo, int hi)
{
}
template <class TYPE> void
TArray<TYPE>::init2(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi)
{
if (data && src)
{
int els=hi-lo+1;
if (els>src_hi-src_lo+1) els=src_hi-src_lo+1;
if (els>0)
memmove((void *) &((TYPE *) data)[lo],
(void *) &((TYPE *) src)[src_lo], els*sizeof(TYPE));
};
}
// inline removed
template <class TYPE> void
TArray<TYPE>::insert(void * data, int els, int where,
const void * what, int howmany)
{
memmove(((TYPE *) data)+where+howmany,
((TYPE *) data)+where, sizeof(TYPE)*(els-where));
for(int i=0;i<howmany;i++)
((TYPE *) data)[where+i]=*(TYPE *) what;
}
template <class TYPE>
TArray<TYPE>::TArray ()
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, init2, insert));
}
template <class TYPE>
TArray<TYPE>::TArray(int hi)
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, init2, insert, hi));
}
template <class TYPE>
TArray<TYPE>::TArray(int lo, int hi)
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, init2, insert, lo, hi));
}
//inline removal ends
/** Dynamic array for general types.
Template class #DArray<TYPE># implements an array of
elements of type #TYPE#. Each element is identified by an integer
subscript. The valid subscripts range is defined by dynamically
adjustable lower- and upper-bounds. Besides accessing and setting
elements, member functions are provided to insert or delete elements at
specified positions.
This template class must be able to access
\begin{itemize}
\item a null constructor #TYPE::TYPE()#,
\item a copy constructor #TYPE::TYPE(const TYPE &)#,
\item and a copy operator #TYPE & operator=(const TYPE &)#.
\end{itemize}
The class offers "copy-on-demand" policy, which means that when you
copy the array object, array elements will stay intact as long as you
don't try to modify them. As soon as you make an attempt to change
array contents, the copying is done automatically and transparently
for you - the procedure that we call "copy-on-demand". This is the main
difference between this class and \Ref{GArray} (now obsolete)
Please note that most of the methods are implemented in the base classes
\Ref{ArrayBase} and \Ref{ArrayBaseT}.
*/
template <class TYPE>
class DArray : public ArrayBaseT<TYPE> {
public:
/** Constructs an empty array. The valid subscript range is initially
empty. Member function #touch# and #resize# provide convenient ways
to enlarge the subscript range. */
DArray(void);
/** Constructs an array with subscripts in range 0 to #hibound#.
The subscript range can be subsequently modified with member functions
#touch# and #resize#.
@param hibound upper bound of the initial subscript range. */
DArray(const int hibound);
/** Constructs an array with subscripts in range #lobound# to #hibound#.
The subscript range can be subsequently modified with member functions
#touch# and #resize#.
@param lobound lower bound of the initial subscript range.
@param hibound upper bound of the initial subscript range. */
DArray(const int lobound, const int hibound);
virtual ~DArray() {};
private:
// Callbacks called from ArrayRep
static void destroy(void * data, int lo, int hi);
static void init1(void * data, int lo, int hi);
static void init2(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi);
static void copy(void * dst, int dst_lo, int dst_hi,
const void * src, int src_lo, int src_hi);
static void insert(void * data, int els, int where,
const void * what, int howmany);
};
template <class TYPE> void
DArray<TYPE>::destroy(void * data, int lo, int hi)
{
if (data)
for(int i=lo;i<=hi;i++)
((TYPE *) data)[i].TYPE::~TYPE();
}
template <class TYPE> void
DArray<TYPE>::init1(void * data, int lo, int hi)
{
if (data)
for(int i=lo;i<=hi;i++)
new ((void *) &((TYPE *) data)[i]) TYPE;
}
template <class TYPE> void
DArray<TYPE>::init2(void * data, int lo, int hi,
const void * src, int src_lo, int src_hi)
{
if (data && src)
{
int i, j;
for(i=lo, j=src_lo;i<=hi && j<=src_hi;i++, j++)
new ((void *) &((TYPE *) data)[i]) TYPE(((TYPE *) src)[j]);
};
}
template <class TYPE> void
DArray<TYPE>::copy(void * dst, int dst_lo, int dst_hi,
const void * src, int src_lo, int src_hi)
{
if (dst && src)
{
int i, j;
for(i=dst_lo, j=src_lo;i<=dst_hi && j<=src_hi;i++, j++)
((TYPE *) dst)[i]=((TYPE *) src)[j];
};
}
template <class TYPE> inline void
DArray<TYPE>::insert(void * data, int els, int where,
const void * what, int howmany)
{
// Now do the insertion
TYPE * d=(TYPE *) data;
int i;
for (i=els+howmany-1; i>=els; i--)
{
if (i-where >= (int)howmany)
new ((void*) &d[i]) TYPE (d[i-howmany]);
else
new ((void*) &d[i]) TYPE (*(TYPE *) what);
}
for (i=els-1; i>=where; i--)
{
if (i-where >= (int)howmany)
d[i] = d[i-howmany];
else
d[i] = *(TYPE *) what;
}
}
template <class TYPE> inline
DArray<TYPE>::DArray ()
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, copy, insert));
}
template <class TYPE> inline
DArray<TYPE>::DArray(const int hi)
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, copy, insert, hi));
}
template <class TYPE> inline
DArray<TYPE>::DArray(const int lo, const int hi)
{
this->assign(new ArrayRep(sizeof(TYPE), destroy, init1,
init2, copy, insert, lo, hi));
}
/** Dynamic array for \Ref{GPBase}d classes.
There are many situations when it's necessary to create arrays of
\Ref{GP} pointers. For example, #DArray<GP<Dialog> ># or #DArray<GP<Button> >#.
This would result in compilation of two instances of \Ref{DArray} because
from the viewpoint of the compiler there are two different classes used
as array elements: #GP<Dialog># and #GP<Button>#. In reality though,
all \Ref{GP} pointers have absolutely the same binary structure because
they are derived from \Ref{GPBase} class and do not add any variables
or virtual functions. That's why it's possible to instantiate \Ref{DArray}
only once for \Ref{GPBase} elements and then just cast types.
To implement this idea we have created this #DPArray<TYPE># class,
which can be used instead of #DArray<GP<TYPE> >#. It behaves absolutely
the same way as \Ref{DArray} but has one big advantage: overhead of
using #DPArray# with one more type is negligible.
*/
template <class TYPE>
class DPArray : public DArray<GPBase> {
public:
// -- CONSTRUCTORS
DPArray();
DPArray(int hibound);
DPArray(int lobound, int hibound);
DPArray(const DPArray<TYPE> &gc);
// -- DESTRUCTOR
virtual ~DPArray();
// -- ACCESS
GP<TYPE>& operator[](int n);
const GP<TYPE>& operator[](int n) const;
// -- CONVERSION
operator GP<TYPE>* ();
#ifndef __MWERKS__ //MCW can't compile
operator const GP<TYPE>* ();
#endif
operator const GP<TYPE>* () const;
// -- ALTERATION
void ins(int n, const GP<TYPE> &val, unsigned int howmany=1);
DPArray<TYPE>& operator= (const DPArray &ga);
};
template<class TYPE>
DPArray<TYPE>::DPArray() {}
template<class TYPE>
DPArray<TYPE>::DPArray(int hibound) :
DArray<GPBase>(hibound) {}
template<class TYPE>
DPArray<TYPE>::DPArray(int lobound, int hibound) :
DArray<GPBase>(lobound, hibound) {}
template<class TYPE>
DPArray<TYPE>::DPArray(const DPArray<TYPE> &gc) :
DArray<GPBase>(gc) {}
template<class TYPE>
DPArray<TYPE>::~DPArray() {}
template<class TYPE>
inline GP<TYPE> &
DPArray<TYPE>::operator[](int n)
{
return (GP<TYPE> &) DArray<GPBase>::operator[](n);
}
template<class TYPE>
inline const GP<TYPE> &
DPArray<TYPE>::operator[](int n) const
{
return (const GP<TYPE> &) DArray<GPBase>::operator[](n);
}
template<class TYPE>
inline DPArray<TYPE>::operator GP<TYPE>* ()
{
return (GP<TYPE> *) DArray<GPBase>::operator GPBase*();
}
#ifndef __MWERKS__ //MCW can't compile
template<class TYPE>
inline DPArray<TYPE>::operator const GP<TYPE>* ()
{
return (const GP<TYPE> *) DArray<GPBase>::operator const GPBase*();
}
#endif
template<class TYPE>
inline DPArray<TYPE>::operator const GP<TYPE>* () const
{
return (const GP<TYPE> *) DArray<GPBase>::operator const GPBase*();
}
template<class TYPE>
inline void
DPArray<TYPE>::ins(int n, const GP<TYPE> & val, unsigned int howmany)
{
DArray<GPBase>::ins(n, val, howmany);
}
template<class TYPE>
inline DPArray<TYPE> &
DPArray<TYPE>::operator= (const DPArray &ga)
{
DArray<GPBase>::operator=(ga);
return *this;
}
// ------------ THE END
//@}
#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif
#endif
|