1// mk4.h --
2// $Id: mk4.h 1669 2007-06-16 00:23:25Z jcw $
3// This is part of Metakit, see http://www.equi4.com/metakit.html
4
5/** @file
6 * Main Metakit library include file
7 */
8
9#ifndef __MK4_H__
10#define __MK4_H__
11
12//---------------------------------------------------------------------------
13//
14//  TITLE
15//
16//      The Metakit Library, by Jean-Claude Wippler, Equi4 Software, NL.
17//
18//  DESCRIPTION
19//
20//      Structured data storage with commit / rollback and on-demand loading.
21//
22//  ACKNOWLEDGEMENTS
23//
24//      To Liesbeth and Myra, for making this possible.
25//
26//---------------------------------------------------------------------------
27//
28//  NAMING CONVENTIONS        PREFIX    REMARKS
29//
30//      Compile time options    q4_     Always defined as 1 or 0, capitalized
31//      Preprocessor defines    d4_     Use with "#ifdef" or "#if defined()"
32//      Classes                 c4_     Classes, listed at start of headers
33//      Typedefs                t4_     Type definitions, if outside classes
34//      Global functions        f4_     Internal, these are rarely defined
35//
36//      Member functions                Start in uppercase
37//      Instance variables      _       And start in lowercase
38//      Static members          _       And start in uppercase
39//
40//      Local variable names            Start in lowercase
41//      Formal parameter names          Start lowercase, end with underscore
42//
43//---------------------------------------------------------------------------
44
45/// Current release = 100 * major + 10 * minor + maintenance
46#define d4_MetakitLibraryVersion 249    // 2.4.9.7 release, Jun 16, 2007
47#define d4_MetaKitLibraryVersion d4_MetakitLibraryVersion // compat, yuck
48
49//---------------------------------------------------------------------------
50// Declarations in this file
51
52class c4_View; // a view on underlying data
53class c4_Cursor; // an index into a view
54class c4_RowRef; // a reference to a row
55class c4_Row; // one row in a view
56class c4_Bytes; // used to pass around generic data
57class c4_Storage; // manages view persistence
58class c4_CustomViewer; // used for customizable views
59class c4_Stream; // abstract stream class
60class c4_Strategy; // system and file interface
61
62class c4_Property; // for access inside rows
63class c4_IntProp;
64class c4_LongProp;
65class c4_FloatProp;
66class c4_DoubleProp;
67class c4_StringProp;
68class c4_BytesProp;
69class c4_ViewProp;
70
71// Everything below is part of the implementation, not for public use
72
73class c4_Sequence; // a collection of rows
74
75class c4_Reference; // refers to the actual data values
76class c4_IntRef;
77class c4_LongRef;
78class c4_FloatRef;
79class c4_DoubleRef;
80class c4_BytesRef;
81class c4_StringRef;
82class c4_ViewRef;
83
84class c4_Dependencies; // not defined here
85class c4_Handler; // not defined here
86class c4_Notifier; // not defined here
87class c4_Persist; // not defined here
88
89//---------------------------------------------------------------------------
90
91// determine whether we need to include "mk4dll.h" to link as DLL
92#if defined (MKDLL_EXPORTS) && !defined (q4_KITDLL)
93#define q4_KITDLL 1
94#endif
95
96// omit floats and doubles in small model 16-bit Intel builds
97#if defined (_DOS) && defined (_M_I86SM) && !defined (q4_TINY)
98#define q4_TINY 1
99#endif
100
101// and here's the other end of the scale...
102#if !defined (_WIN32) && !defined (q4_LONG64)
103#if defined (_PA_RISC2_0) || defined (__powerpc64__) || defined(__sparcv9) || \
104defined(__x86_64__) || defined(__s390x__) || defined(__alpha) ||  \
105  (defined(__ia64) && (!defined(__HP_aCC) || defined(__LP64__))) || \
106  (defined(__APPLE__) && defined(__LP64__))
107#define q4_LONG64 1
108#endif
109#endif
110
111// default to inlining for maximum performance
112#if !defined (q4_INLINE)
113#define q4_INLINE 1
114#endif
115
116//---------------------------------------------------------------------------
117
118// Borland C++ and C++ Builder
119#if defined (__BORLANDC__)
120// by default, if runtime is linked as a DLL, then so is Metakit
121#if defined (_RTLDLL) && !defined (q4_KITDLL)
122#define q4_KITDLL 1
123#endif
124
125// Borland 5.0 supports the bool datatype
126#if __BORLANDC__ >= 0x500
127#define q4_BOOL 1
128#endif
129#endif // __BORLANDC__
130
131// IRIX supports the bool datatype
132// define before gcc to cover both the gcc and MipsPRO compiler
133#if defined (sgi)
134#define q4_BOOL 1
135#undef bool
136#undef true
137#undef false
138#endif
139
140// GNU gcc/egcs
141#if defined (__GNUC__)
142#ifndef q4_BOOL
143#define q4_BOOL 1
144#endif
145#ifndef HAVE_LONG_LONG
146#define HAVE_LONG_LONG 1
147#endif
148#endif
149
150// HP aCC
151#if defined (__HP_aCC)
152#ifndef HAVE_LONG_LONG
153#define HAVE_LONG_LONG 1
154#endif
155#endif
156
157// Metrowerks CodeWarrior
158#if defined (__MWERKS__)
159#if __option(bool)
160#define q4_BOOL 1       // bool datatype is optionally supported
161// undef, these conflict with c4_Storage::c4_Storage overloading
162#undef bool
163#undef true
164#undef false
165#endif
166#endif
167
168// Microsoft Visual C++
169#if defined (_MSC_VER)
170// MSVC 5.0 supports the bool datatype, MSVC 4.x has no namespaces
171#if _MSC_VER >= 1100
172#define q4_BOOL 1
173#define LONG_LONG __int64
174#else
175#define q4_NO_NS 1
176#endif
177
178// a kludge to avoid having to use ugly DLL exprt defs in this header
179#pragma warning(disable: 4273) // inconsistent dll linkage
180#endif // _MSC_VER
181
182//---------------------------------------------------------------------------
183// Other definitions needed by the public Metakit library header files
184
185#if !q4_BOOL && !q4_STD         // define a bool datatype
186#define false 0
187#define true 1
188#define bool int
189#endif
190
191#if q4_KITDLL                   // add declaration specifiers
192#include "mk4dll.h"
193#endif
194
195#if q4_INLINE                   // enable inline expansion
196#define d4_inline inline
197#else
198#define d4_inline
199#endif
200
201typedef unsigned char t4_byte; // create typedefs for t4_byte, etc.
202
203#if q4_LONG64
204typedef int t4_i32; // if longs are 64b, then int must be 32b
205#else
206typedef long t4_i32; // if longs aren't 64b, then they are 32b
207#endif
208
209#if q4_LONG64           // choose a way to represent 64b integers
210typedef long t4_i64;
211#elif defined (LONG_LONG)
212typedef LONG_LONG t4_i64;
213#elif HAVE_LONG_LONG
214typedef long long t4_i64;
215#else
216struct t4_i64 {
217    long l1;
218    long l2;
219};
220bool operator == (const t4_i64 a_, const t4_i64 b_);
221bool operator < (const t4_i64 a_, const t4_i64 b_);
222#endif
223
224//---------------------------------------------------------------------------
225
226class c4_View {
227  protected:
228    c4_Sequence *_seq;
229
230  public:
231    /* Construction / destruction / assignment */
232    c4_View(c4_Sequence * = 0);
233    c4_View(c4_CustomViewer*);
234    c4_View(c4_Stream*);
235    c4_View(const c4_Property &property_);
236    c4_View(const c4_View &);
237    ~c4_View();
238
239    c4_View &operator = (const c4_View &);
240    c4_Persist *Persist()const; // added 16-11-2000 to simplify c4_Storage
241
242    /* Getting / setting the number of rows */
243    int GetSize()const;
244    void SetSize(int, int =  - 1);
245
246    void RemoveAll();
247
248    /*: Getting / setting individual elements */
249    c4_RowRef GetAt(int)const;
250    c4_RowRef operator[](int)const;
251
252    void SetAt(int, const c4_RowRef &);
253    c4_RowRef ElementAt(int);
254
255    bool GetItem(int, int, c4_Bytes &)const;
256    void SetItem(int, int, const c4_Bytes &)const;
257
258    /* These can increase the number of rows */
259    void SetAtGrow(int, const c4_RowRef &);
260    int Add(const c4_RowRef &);
261
262    /* Insertion / deletion of rows */
263    void InsertAt(int, const c4_RowRef &, int = 1);
264    void RemoveAt(int, int = 1);
265    void InsertAt(int, const c4_View &);
266
267    bool IsCompatibleWith(const c4_View &)const;
268    void RelocateRows(int, int, c4_View &, int);
269
270    /* Dealing with the properties of this view */
271    int NumProperties()const;
272    const c4_Property &NthProperty(int)const;
273    int FindProperty(int);
274    int FindPropIndexByName(const char*)const;
275    c4_View Duplicate()const;
276    c4_View Clone()const;
277    int AddProperty(const c4_Property &);
278    c4_View operator, (const c4_Property &)const;
279
280    const char *Description()const;
281
282    /* Derived views */
283    c4_View Sort()const;
284    c4_View SortOn(const c4_View &)const;
285    c4_View SortOnReverse(const c4_View &, const c4_View &)const;
286
287    c4_View Select(const c4_RowRef &)const;
288    c4_View SelectRange(const c4_RowRef &, const c4_RowRef &)const;
289
290    c4_View Project(const c4_View &)const;
291    c4_View ProjectWithout(const c4_View &)const;
292
293    int GetIndexOf(const c4_RowRef &)const;
294    int RestrictSearch(const c4_RowRef &, int &, int &);
295
296    /* Custom views */
297    c4_View Slice(int, int =  - 1, int = 1)const;
298    c4_View Product(const c4_View &)const;
299    c4_View RemapWith(const c4_View &)const;
300    c4_View Pair(const c4_View &)const;
301    c4_View Concat(const c4_View &)const;
302    c4_View Rename(const c4_Property &, const c4_Property &)const;
303
304    c4_View GroupBy(const c4_View &, const c4_ViewProp &)const;
305    c4_View Counts(const c4_View &, const c4_IntProp &)const;
306    c4_View Unique()const;
307
308    c4_View Union(const c4_View &)const;
309    c4_View Intersect(const c4_View &)const;
310    c4_View Different(const c4_View &)const;
311    c4_View Minus(const c4_View &)const;
312
313    c4_View JoinProp(const c4_ViewProp &, bool = false)const;
314    c4_View Join(const c4_View &, const c4_View &, bool = false)const;
315
316    c4_View ReadOnly()const;
317    c4_View Hash(const c4_View &, int = 1)const;
318    c4_View Blocked()const;
319    c4_View Ordered(int = 1)const;
320    c4_View Indexed(const c4_View &, const c4_View &, bool = false)const;
321
322    /* Searching */
323    int Find(const c4_RowRef &, int = 0)const;
324    int Search(const c4_RowRef &)const;
325    int Locate(const c4_RowRef &, int * = 0)const;
326
327    /* Comparing view contents */
328    int Compare(const c4_View &)const;
329
330    friend bool operator == (const c4_View &, const c4_View &);
331    friend bool operator != (const c4_View &, const c4_View &);
332    friend bool operator < (const c4_View &, const c4_View &);
333    friend bool operator > (const c4_View &, const c4_View &);
334    friend bool operator <= (const c4_View &, const c4_View &);
335    friend bool operator >= (const c4_View &, const c4_View &);
336
337  protected:
338    void _IncSeqRef();
339    void _DecSeqRef();
340
341    /// View references are allowed to peek inside view objects
342    friend class c4_ViewRef;
343
344    // DROPPED: Structure() const;
345    // DROPPED: Description(const c4_View& view_);
346};
347
348//---------------------------------------------------------------------------
349
350#if defined(os_aix) && defined(compiler_ibmcxx) && (compiler_ibmcxx > 500)
351bool operator == (const c4_RowRef &a_, const c4_RowRef &b_);
352bool operator != (const c4_RowRef &a_, const c4_RowRef &b_);
353bool operator <= (const c4_RowRef &a_, const c4_RowRef &b_);
354bool operator >= (const c4_RowRef &a_, const c4_RowRef &b_);
355bool operator > (const c4_RowRef &a_, const c4_RowRef &b_);
356bool operator < (const c4_RowRef &a_, const c4_RowRef &b_);
357#endif
358
359class c4_Cursor {
360  public:
361    /// Pointer to the sequence
362    c4_Sequence *_seq;
363    /// Current index into the sequence
364    int _index;
365
366    /* Construction / destruction / dereferencing */
367    /// Construct a new cursor
368    c4_Cursor(c4_Sequence &, int);
369
370    /// Dereference this cursor to "almost" a row
371    c4_RowRef operator *()const;
372
373    /// This is the same as *(cursor + offset)
374    c4_RowRef operator[](int)const;
375
376    /* Stepping the iterator forwards / backwards */
377    /// Pre-increment the cursor
378    c4_Cursor &operator++();
379    /// Post-increment the cursor
380    c4_Cursor operator++(int);
381    /// Pre-decrement the cursor
382    c4_Cursor &operator--();
383    /// Post-decrement the cursor
384    c4_Cursor operator--(int);
385
386    /// Advance by a given offset
387    c4_Cursor &operator += (int);
388    /// Back up by a given offset
389    c4_Cursor &operator -= (int);
390
391    /// Subtract a specified offset
392    c4_Cursor operator - (int)const;
393    /// Return the distance between two cursors
394    int operator - (c4_Cursor)const;
395
396    /// Add specified offset
397    friend c4_Cursor operator + (c4_Cursor, int);
398    /// Add specified offset to cursor
399    friend c4_Cursor operator + (int, c4_Cursor);
400
401    /* Comparing row positions */
402    /// Return true if both cursors are equal
403    friend bool operator == (c4_Cursor, c4_Cursor);
404    /// Return true if both cursors are not equal
405    friend bool operator != (c4_Cursor, c4_Cursor);
406    /// True if first cursor is less than second cursor
407    friend bool operator < (c4_Cursor, c4_Cursor);
408    /// True if first cursor is greater than second cursor
409    friend bool operator > (c4_Cursor, c4_Cursor);
410    /// True if first cursor is less or equal to second cursor
411    friend bool operator <= (c4_Cursor, c4_Cursor);
412    /// True if first cursor is greater or equal to second cursor
413    friend bool operator >= (c4_Cursor, c4_Cursor);
414
415    /* Comparing row contents */
416    /// Return true if the contents of both rows are equal
417    friend bool operator == (const c4_RowRef &, const c4_RowRef &);
418    /// Return true if the contents of both rows are not equal
419    friend bool operator != (const c4_RowRef &, const c4_RowRef &);
420    /// True if first row is less than second row
421    friend bool operator < (const c4_RowRef &, const c4_RowRef &);
422    /// True if first row is greater than second row
423    friend bool operator > (const c4_RowRef &, const c4_RowRef &);
424    /// True if first row is less or equal to second row
425    friend bool operator <= (const c4_RowRef &, const c4_RowRef &);
426    /// True if first row is greater or equal to second row
427    friend bool operator >= (const c4_RowRef &, const c4_RowRef &);
428};
429
430//---------------------------------------------------------------------------
431
432class c4_RowRef {
433    /// A row reference is a cursor in disguise
434    c4_Cursor _cursor;
435
436  public:
437    /* General operations */
438    /// Assign the value of another row to this one
439    c4_RowRef operator = (const c4_RowRef &);
440    /// Return the cursor associated to this row
441    c4_Cursor operator &()const;
442    /// Return the underlying container view
443    c4_View Container()const;
444
445  protected:
446    /// Constructor, not for general use
447    c4_RowRef(c4_Cursor);
448
449    friend class c4_Cursor;
450    friend class c4_Row;
451};
452
453//---------------------------------------------------------------------------
454/// An entry in a collection with copy semantics.
455//
456//  Rows can exist by themselves and as contents of views.  Row assignment
457//  implies that a copy of the contents of the originating row is made.
458//
459//  A row is implemented as an unattached view with exactly one element.
460
461class c4_Row: public c4_RowRef {
462  public:
463    /// Construct a row with no properties
464    c4_Row();
465    /// Construct a row from another one
466    c4_Row(const c4_Row &);
467    /// Construct a row copy from a row reference
468    c4_Row(const c4_RowRef &);
469    /// Destructor
470    ~c4_Row();
471
472    /// Assign a copy of another row to this one
473    c4_Row &operator = (const c4_Row &);
474    /// Copy another row to this one
475    c4_Row &operator = (const c4_RowRef &);
476
477    /// Add all properties and values into this row
478    void ConcatRow(const c4_RowRef &);
479    /// Return a new row which is the concatenation of two others
480    friend c4_Row operator + (const c4_RowRef &, const c4_RowRef &);
481
482  private:
483    static c4_Cursor Allocate();
484    static void Release(c4_Cursor);
485};
486
487//---------------------------------------------------------------------------
488
489class c4_Bytes {
490    union {
491        t4_byte _buffer[16];
492        double _aligner; // on a Sparc, the int below wasn't enough...
493    };
494
495    t4_byte *_contents;
496    int _size;
497    bool _copy;
498
499  public:
500    c4_Bytes();
501    c4_Bytes(const void *, int);
502    c4_Bytes(const void *, int, bool);
503    c4_Bytes(const c4_Bytes &);
504    ~c4_Bytes();
505
506    c4_Bytes &operator = (const c4_Bytes &);
507    void Swap(c4_Bytes &);
508
509    int Size()const;
510    const t4_byte *Contents()const;
511
512    t4_byte *SetBuffer(int);
513    t4_byte *SetBufferClear(int);
514
515    friend bool operator == (const c4_Bytes &, const c4_Bytes &);
516    friend bool operator != (const c4_Bytes &, const c4_Bytes &);
517
518  private:
519    void _MakeCopy();
520    void _LoseCopy();
521};
522
523//---------------------------------------------------------------------------
524
525class c4_Storage: public c4_View {
526  public:
527    /// Construct streaming-only storage object
528    c4_Storage();
529    /// Construct a storage using the specified strategy handler
530    c4_Storage(c4_Strategy &, bool = false, int = 1);
531    /// Construct a storage object, keeping the current structure
532    c4_Storage(const char *, int);
533    /// Reconstruct a storage object from a suitable view
534    c4_Storage(const c4_View &);
535    /// Destructor, usually closes file, but does not commit by default
536    ~c4_Storage();
537
538    void SetStructure(const char*);
539    bool AutoCommit(bool = true);
540    c4_Strategy &Strategy()const;
541    const char *Description(const char * = 0);
542
543    bool SetAside(c4_Storage &);
544    c4_Storage *GetAside()const;
545
546    bool Commit(bool = false);
547    bool Rollback(bool = false);
548
549    c4_ViewRef View(const char*);
550    c4_View GetAs(const char*);
551
552    bool LoadFrom(c4_Stream &);
553    void SaveTo(c4_Stream &);
554
555    t4_i32 FreeSpace(t4_i32 *bytes_ = 0);
556
557    //DROPPED: c4_Storage (const char* filename_, const char* description_);
558    //DROPPED: c4_View Store(const char* name_, const c4_View& view_);
559    //DROPPED: c4_HandlerSeq& RootTable() const;
560    //DROPPED: c4_RowRef xContents() const;
561
562  private:
563    void Initialize(c4_Strategy &, bool, int);
564};
565
566//---------------------------------------------------------------------------
567
568class c4_Property {
569    short _id;
570    char _type;
571
572  public:
573    /// Construct a new property with the give type and id
574    c4_Property(char, int);
575    /// Construct a new property with the give type and name
576    c4_Property(char, const char*);
577    ~c4_Property();
578
579    c4_Property(const c4_Property &);
580    void operator = (const c4_Property &);
581
582    const char *Name()const;
583    char Type()const;
584
585    int GetId()const;
586
587    c4_Reference operator()(const c4_RowRef &)const;
588
589    void Refs(int)const;
590
591    c4_View operator, (const c4_Property &)const;
592
593    static void CleanupInternalData();
594};
595
596/// Integer properties.
597class c4_IntProp: public c4_Property {
598  public:
599    /// Construct a new property
600    c4_IntProp(const char*);
601    /// Destructor
602    ~c4_IntProp();
603
604    /// Get or set an integer property in a row
605    c4_IntRef operator()(const c4_RowRef &)const;
606    /// Get an integer property in a row
607    t4_i32 Get(const c4_RowRef &)const;
608    /// Set an integer property in a row
609    void Set(const c4_RowRef &, t4_i32)const;
610
611    /// Creates a row with one integer, shorthand for AsRow.
612    c4_Row operator[](t4_i32)const;
613    /// Creates a row with one integer.
614    c4_Row AsRow(t4_i32)const;
615};
616
617#if !q4_TINY
618
619/// Long int properties.
620class c4_LongProp: public c4_Property {
621  public:
622    /// Construct a new property
623    c4_LongProp(const char*);
624    /// Destructor
625    ~c4_LongProp();
626
627    /// Get or set a long int property in a row
628    c4_LongRef operator()(const c4_RowRef &)const;
629    /// Get a long int property in a row
630    t4_i64 Get(const c4_RowRef &)const;
631    /// Set a long int property in a row
632    void Set(const c4_RowRef &, t4_i64)const;
633
634    /// Creates a row with one long int, shorthand for AsRow.
635    c4_Row operator[](t4_i64)const;
636    /// Creates a row with one long int.
637    c4_Row AsRow(t4_i64)const;
638};
639
640/// Floating point properties.
641class c4_FloatProp: public c4_Property {
642  public:
643    /// Construct a new property
644    c4_FloatProp(const char*);
645    /// Destructor
646    ~c4_FloatProp();
647
648    /// Get or set a floating point property in a row
649    c4_FloatRef operator()(const c4_RowRef &)const;
650    /// Get a floating point property in a row
651    double Get(const c4_RowRef &)const;
652    /// Set a floating point property in a row
653    void Set(const c4_RowRef &, double)const;
654
655    /// Create a row with one floating point value, shorthand for AsRow
656    c4_Row operator[](double)const;
657    /// Create a row with one floating point value
658    c4_Row AsRow(double)const;
659};
660
661/// Double precision properties.
662class c4_DoubleProp: public c4_Property {
663  public:
664    /// Construct a new property.
665    c4_DoubleProp(const char*);
666    /// Destructor
667    ~c4_DoubleProp();
668
669    /// Get or set a double precision property in a row
670    c4_DoubleRef operator()(const c4_RowRef &)const;
671    /// Get a double precision property in a row
672    double Get(const c4_RowRef &)const;
673    /// Set a double precision property in a row
674    void Set(const c4_RowRef &, double)const;
675
676    /// Create a row with one double precision value, shorthand for AsRow
677    c4_Row operator[](double)const;
678    /// Create a row with one double precision value
679    c4_Row AsRow(double)const;
680};
681#endif // !q4_TINY
682
683/// String properties.
684class c4_StringProp: public c4_Property {
685  public:
686    /// Construct a new property
687    c4_StringProp(const char*);
688    /// Destructor
689    ~c4_StringProp();
690
691    /// Get or set a string property in a row
692    c4_StringRef operator()(const c4_RowRef &)const;
693    /// Get a string property in a row
694    const char *Get(const c4_RowRef &)const;
695    /// Set a string property in a row
696    void Set(const c4_RowRef &, const char*)const;
697
698    /// Create a row with one string, shorthand for AsRow
699    c4_Row operator[](const char*)const;
700    /// Create a row with one string
701    c4_Row AsRow(const char*)const;
702};
703
704/// Binary properties.
705class c4_BytesProp: public c4_Property {
706  public:
707    /// Construct a new property
708    c4_BytesProp(const char*);
709    /// Destructor
710    ~c4_BytesProp();
711
712    /// Get or set a bytes property in a row
713    c4_BytesRef operator()(const c4_RowRef &)const;
714    /// Get a bytes property in a row
715    c4_Bytes Get(const c4_RowRef &)const;
716    /// Set a bytes property in a row
717    void Set(const c4_RowRef &, const c4_Bytes &)const;
718
719    /// Create a row with one bytes object, shorthand for AsRow
720    c4_Row operator[](const c4_Bytes &)const;
721    /// Create a row with one bytes object
722    c4_Row AsRow(const c4_Bytes &)const;
723};
724
725/// View properties.
726class c4_ViewProp: public c4_Property {
727  public:
728    /// Construct a new property
729    c4_ViewProp(const char*);
730    /// Destructor
731    ~c4_ViewProp();
732
733    /// Get or set a view property in a row
734    c4_ViewRef operator()(const c4_RowRef &)const;
735    /// Get a view property in a row
736    c4_View Get(const c4_RowRef &)const;
737    /// Set a view property in a row
738    void Set(const c4_RowRef &, const c4_View &)const;
739
740    /// Create a row with one view, shorthand for AsRow
741    c4_Row operator[](const c4_View &)const;
742    /// Create a row with one view
743    c4_Row AsRow(const c4_View &)const;
744};
745
746//---------------------------------------------------------------------------
747
748class c4_CustomViewer {
749  protected:
750    /// Constructor, must be overriden in derived class
751    c4_CustomViewer();
752  public:
753    /// Destructor
754    virtual ~c4_CustomViewer();
755
756    /// Return the structure of this view (initialization, called once)
757    virtual c4_View GetTemplate() = 0;
758    /// Return the number of rows in this view
759    virtual int GetSize() = 0;
760    int Lookup(const c4_RowRef &, int &);
761    virtual int Lookup(c4_Cursor, int &);
762    /// Fetch one data item, return it as a generic data value
763    virtual bool GetItem(int, int, c4_Bytes &) = 0;
764    virtual bool SetItem(int, int, const c4_Bytes &);
765    bool InsertRows(int, const c4_RowRef &, int = 1);
766    virtual bool InsertRows(int, c4_Cursor, int = 1);
767    virtual bool RemoveRows(int, int = 1);
768};
769
770//---------------------------------------------------------------------------
771/// A stream is a virtual helper class to serialize in binary form.
772
773class c4_Stream {
774  public:
775    virtual ~c4_Stream();
776
777    /// Fetch some bytes sequentially
778    virtual int Read(void *, int) = 0;
779    /// Store some bytes sequentially
780    virtual bool Write(const void *, int) = 0;
781};
782
783//---------------------------------------------------------------------------
784/// A strategy encapsulates code dealing with the I/O system interface.
785
786class c4_Strategy {
787  public:
788    c4_Strategy();
789    virtual ~c4_Strategy();
790
791    virtual bool IsValid()const;
792    virtual int DataRead(t4_i32, void *, int);
793    virtual void DataWrite(t4_i32, const void *, int);
794    virtual void DataCommit(t4_i32);
795    virtual void ResetFileMapping();
796    virtual t4_i32 FileSize();
797    virtual t4_i32 FreshGeneration();
798
799    void SetBase(t4_i32);
800    t4_i32 EndOfData(t4_i32 =  - 1);
801
802    /// True if the storage format is not native (default is false)
803    bool _bytesFlipped;
804    /// Error code of last failed I/O operation, zero if I/O was ok
805    int _failure;
806    /// First byte in file mapping, zero if not active
807    const t4_byte *_mapStart;
808    /// Number of bytes filled with active data
809    t4_i32 _dataSize;
810    /// All file positions are relative to this offset
811    t4_i32 _baseOffset;
812    /// The root position of the shallow tree walks
813    t4_i32 _rootPos;
814    /// The size of the root column
815    t4_i32 _rootLen;
816};
817
818//---------------------------------------------------------------------------
819/// A sequence is an abstract base class for views on ranges of records.
820//
821//  Sequences represent arrays of rows (or indexed collections / tables).
822//  Insertion and removal of entries is allowed, but could take linear time.
823//  A reference count is maintained to decide when the object should go away.
824
825class c4_Sequence {
826    /// Reference count
827    int _refCount;
828    /// Pointer to dependency list, or null if nothing depends on this
829    c4_Dependencies *_dependencies;
830
831  protected:
832    /// Optimization: cached property index
833    int _propertyLimit;
834    /// Optimization: property map for faster access
835    short *_propertyMap; // see c4_HandlerSeq::Reset()
836    /// allocated on first use by c4_Sequence::Buffer()
837    c4_Bytes *_tempBuf;
838
839  public:
840    /* General */
841    /// Abstract constructor
842    c4_Sequence();
843
844    virtual int Compare(int, c4_Cursor)const;
845    virtual bool RestrictSearch(c4_Cursor, int &, int &);
846    void SetAt(int, c4_Cursor);
847    virtual int RemapIndex(int, const c4_Sequence*)const;
848
849    /* Reference counting */
850    void IncRef();
851    void DecRef();
852    int NumRefs()const;
853
854    /* Adding / removing rows */
855    /// Return the current number of rows
856    virtual int NumRows()const = 0;
857    void Resize(int, int =  - 1);
858
859    virtual void InsertAt(int, c4_Cursor, int = 1);
860    virtual void RemoveAt(int, int = 1);
861    virtual void Move(int, int);
862
863    /* Properties */
864    int NthPropId(int)const;
865    int PropIndex(int);
866    int PropIndex(const c4_Property &);
867
868    /// Return the number of data handlers in this sequence
869    virtual int NumHandlers()const = 0;
870    /// Return a reference to the N-th handler in this sequence
871    virtual c4_Handler &NthHandler(int)const = 0;
872    /// Return the context of the N-th handler in this sequence
873    virtual const c4_Sequence *HandlerContext(int)const = 0;
874    /// Add the specified data handler to this sequence
875    virtual int AddHandler(c4_Handler*) = 0;
876    /// Create a handler of the appropriate type
877    virtual c4_Handler *CreateHandler(const c4_Property &) = 0;
878
879    virtual const char *Description();
880
881    /* Element access */
882    /// Return width of specified data item
883    virtual int ItemSize(int, int);
884    /// Retrieve one data item from this sequence
885    virtual bool Get(int, int, c4_Bytes &);
886    /// Store a data item into this sequence
887    virtual void Set(int, const c4_Property &, const c4_Bytes &);
888
889    /* Dependency notification */
890    void Attach(c4_Sequence*);
891    void Detach(c4_Sequence*);
892    /// Return a pointer to the dependencies, or null
893    c4_Dependencies *GetDependencies()const;
894
895    virtual c4_Notifier *PreChange(c4_Notifier &);
896    virtual void PostChange(c4_Notifier &);
897
898    const char *UseTempBuffer(const char*);
899
900  protected:
901    virtual ~c4_Sequence();
902
903    void ClearCache();
904
905  public:
906    //! for c4_Table::Sequence setup
907    virtual void SetNumRows(int) = 0;
908    virtual c4_Persist *Persist()const;
909
910    c4_Bytes &Buffer();
911
912  private:
913    c4_Sequence(const c4_Sequence &); // not implemented
914    void operator = (const c4_Sequence &); // not implemented
915};
916
917//---------------------------------------------------------------------------
918/// A reference is used to get or set typed data, using derived classes.
919//
920//  Objects of this class are only intended to be used as a temporary handle
921//  while getting and setting properties in a row.  They are normally only
922//  constructed as result of function overload operators: "property (row)".
923
924class c4_Reference {
925  protected:
926    /// The cursor which points to the data
927    c4_Cursor _cursor;
928    /// The property associated to this reference
929    const c4_Property &_property;
930
931  public:
932    /// Constructor
933    c4_Reference(const c4_RowRef &, const c4_Property &);
934
935    /// Assignment of one data item
936    c4_Reference &operator = (const c4_Reference &);
937
938    /// Return width of the referenced data item
939    int GetSize()const;
940    /// Retrieve the value of the referenced data item
941    bool GetData(c4_Bytes &)const;
942    /// Store a value into the referenced data item
943    void SetData(const c4_Bytes &)const;
944
945    /// Return true if the contents of both references is equal
946    friend bool operator == (const c4_Reference &, const c4_Reference &);
947    /// Return true if the contents of both references is not equal
948    friend bool operator != (const c4_Reference &, const c4_Reference &);
949
950  private:
951    void operator &()const; // not implemented
952};
953
954//---------------------------------------------------------------------------
955
956/// Used to get or set integer values.
957class c4_IntRef: public c4_Reference {
958  public:
959    /// Constructor
960    c4_IntRef(const c4_Reference &);
961    /// Get the value as integer
962    operator t4_i32()const;
963    /// Set the value to the specified integer
964    c4_IntRef &operator = (t4_i32);
965};
966
967#if !q4_TINY
968
969/// Used to get or set long int values.
970class c4_LongRef: public c4_Reference {
971  public:
972    /// Constructor
973    c4_LongRef(const c4_Reference &);
974    /// Get the value as long int
975    operator t4_i64()const;
976    /// Set the value to the specified long int
977    c4_LongRef &operator = (t4_i64);
978};
979
980/// Used to get or set floating point values.
981class c4_FloatRef: public c4_Reference {
982  public:
983    /// Constructor
984    c4_FloatRef(const c4_Reference &);
985    /// Get the value as floating point
986    operator double()const;
987    /// Set the value to the specified floating point
988    c4_FloatRef &operator = (double);
989};
990
991/// Used to get or set double precision values.
992class c4_DoubleRef: public c4_Reference {
993  public:
994    /// Constructor
995    c4_DoubleRef(const c4_Reference &);
996    /// Get the value as floating point
997    operator double()const;
998    /// Set the value to the specified floating point
999    c4_DoubleRef &operator = (double);
1000};
1001
1002#endif // !q4_TINY
1003
1004/// Used to get or set binary object values.
1005class c4_BytesRef: public c4_Reference {
1006  public:
1007    /// Constructor
1008    c4_BytesRef(const c4_Reference &);
1009    /// Get the value as binary object
1010    operator c4_Bytes()const;
1011    /// Set the value to the specified binary object
1012    c4_BytesRef &operator = (const c4_Bytes &);
1013
1014    /// Fetch data from the memo field, up to end if length is zero
1015    c4_Bytes Access(t4_i32, int = 0, bool = false)const;
1016    /// Store data, resize by diff_ bytes, return true if successful
1017    bool Modify(const c4_Bytes &, t4_i32, int = 0)const;
1018};
1019
1020/// Used to get or set string values.
1021class c4_StringRef: public c4_Reference {
1022  public:
1023    /// Constructor
1024    c4_StringRef(const c4_Reference &);
1025    /// Get the value as string
1026    operator const char *()const;
1027    /// Set the value to the specified string
1028    c4_StringRef &operator = (const char*);
1029};
1030
1031/// Used to get or set view values.
1032class c4_ViewRef: public c4_Reference {
1033  public:
1034    /// Constructor
1035    c4_ViewRef(const c4_Reference &);
1036    /// Get the value as view
1037    operator c4_View()const;
1038    /// Set the value to the specified view
1039    c4_ViewRef &operator = (const c4_View &);
1040};
1041
1042//---------------------------------------------------------------------------
1043// Debug logging option, can generate log of changes for one/all properties
1044
1045#if q4_LOGPROPMODS
1046FILE *f4_LogPropMods(FILE *fp_, int propId_);
1047#else
1048#define f4_LogPropMods(a,b) 0
1049#endif
1050
1051//---------------------------------------------------------------------------
1052
1053#if q4_INLINE
1054#include "mk4.inl"
1055#endif
1056
1057//---------------------------------------------------------------------------
1058
1059#endif // __MK4_H__
1060