File indexing completed on 2025-01-26 04:47:04

0001 // mk4.h --
0002 // This is part of Metakit, see http://www.equi4.com/metakit/
0003 
0004 /** @file
0005  * Main Metakit library include file
0006  */
0007 
0008 #pragma once
0009 
0010 //---------------------------------------------------------------------------
0011 //
0012 //  TITLE
0013 //
0014 //      The Metakit Library, by Jean-Claude Wippler, Equi4 Software, NL.
0015 //
0016 //  DESCRIPTION
0017 //
0018 //      Structured data storage with commit / rollback and on-demand loading.
0019 //
0020 //  ACKNOWLEDGEMENTS
0021 //
0022 //      To Liesbeth and Myra, for making this possible.
0023 //
0024 //---------------------------------------------------------------------------
0025 //
0026 //  NAMING CONVENTIONS        PREFIX    REMARKS
0027 //
0028 //      Compile time options    q4_     Always defined as 1 or 0, capitalized
0029 //      Preprocessor defines    d4_     Use with "#ifdef" or "#if defined()"
0030 //      Classes                 c4_     Classes, listed at start of headers
0031 //      Typedefs                t4_     Type definitions, if outside classes
0032 //      Global functions        f4_     Internal, these are rarely defined
0033 //
0034 //      Member functions                Start in uppercase
0035 //      Instance variables      _       And start in lowercase
0036 //      Static members          _       And start in uppercase
0037 //
0038 //      Local variable names            Start in lowercase
0039 //      Formal parameter names          Start lowercase, end with underscore
0040 //
0041 //---------------------------------------------------------------------------
0042 
0043 /// Current release = 100 * major + 10 * minor + maintenance
0044 #define d4_MetakitLibraryVersion 249    // 2.4.9.5 release, Nov 22, 2005
0045 #define d4_MetaKitLibraryVersion d4_MetakitLibraryVersion // compat, yuck
0046 
0047 //---------------------------------------------------------------------------
0048 // Declarations in this file
0049 
0050 class c4_View;                      // a view on underlying data
0051 class c4_Cursor;                    // an index into a view
0052 class c4_RowRef;                    // a reference to a row
0053 class c4_Row;                   // one row in a view
0054 class c4_Bytes;                     // used to pass around generic data
0055 class c4_Storage;                   // manages view persistence
0056 class c4_CustomViewer;              // used for customizable views
0057 class c4_Stream;                    // abstract stream class
0058 class c4_Strategy;                  // system and file interface
0059 
0060 class c4_Property;                  // for access inside rows
0061 class c4_IntProp;
0062 class c4_LongProp;
0063 class c4_FloatProp;
0064 class c4_DoubleProp;
0065 class c4_StringProp;
0066 class c4_BytesProp;
0067 class c4_ViewProp;
0068 
0069 // Everything below is part of the implementation, not for public use
0070 
0071 class c4_Sequence;                  // a collection of rows
0072 
0073 class c4_Reference;                 // refers to the actual data values
0074 class c4_IntRef;
0075 class c4_LongRef;
0076 class c4_FloatRef;
0077 class c4_DoubleRef;
0078 class c4_BytesRef;
0079 class c4_StringRef;
0080 class c4_ViewRef;
0081 
0082 class c4_Dependencies;              // not defined here
0083 class c4_Handler;                   // not defined here
0084 class c4_Notifier;                  // not defined here
0085 class c4_Persist;                   // not defined here
0086 
0087 //---------------------------------------------------------------------------
0088 
0089 // determine whether we need to include "mk4dll.h" to link as DLL
0090 #if defined (MKDLL_EXPORTS) && !defined (q4_KITDLL)
0091 #define q4_KITDLL 1
0092 #endif
0093 
0094 // omit floats and doubles in small model 16-bit Intel builds
0095 #if defined (_DOS) && defined (_M_I86SM) && !defined (q4_TINY)
0096 #define q4_TINY 1
0097 #endif
0098 
0099 // and here's the other end of the scale...
0100 #if !defined (_WIN32) && !defined (q4_LONG64)
0101 #if (defined (_PA_RISC2_0) && defined(__hpux)) || defined (__powerpc64__) || defined(__sparcv9)    \
0102     || defined (__x86_64__) || defined (__s390x__) || defined (__alpha) || defined (__mips64)    \
0103     || (defined (__ia64) && (!defined (__HP_aCC) || defined(__LP64__)))
0104 #define q4_LONG64 1
0105 #endif
0106 #endif
0107 
0108 // default to inlining for maximum performance
0109 #if !defined (q4_INLINE)
0110 #define q4_INLINE 1
0111 #endif
0112 
0113 //---------------------------------------------------------------------------
0114 
0115 // Borland C++ and C++ Builder
0116 #if defined (__BORLANDC__)
0117 // by default, if runtime is linked as a DLL, then so is Metakit
0118 #if defined (_RTLDLL) && !defined (q4_KITDLL)
0119 #define q4_KITDLL 1
0120 #endif
0121 
0122 // Borland 5.0 supports the bool datatype
0123 #if __BORLANDC__ >= 0x500
0124 #define q4_BOOL 1
0125 #endif
0126 #endif // __BORLANDC__
0127 
0128 // IRIX supports the bool datatype
0129 // define before gcc to cover both the gcc and MipsPRO compiler
0130 #if defined (sgi)
0131 #define q4_BOOL 1
0132 #undef bool
0133 #undef true
0134 #undef false
0135 #endif
0136 
0137 #if defined (__SUNPRO_CC)
0138 #define q4_BOOL 1
0139 #ifdef bool
0140 #undef bool
0141 #undef true
0142 #undef false
0143 #endif
0144 #endif
0145 
0146 // GNU gcc/egcs
0147 #if defined (__GNUC__)
0148 #if !defined(q4_BOOL)
0149 #define q4_BOOL 1
0150 #endif
0151 #if !defined(HAVE_LONG_LONG)
0152 #define HAVE_LONG_LONG 1
0153 #endif
0154 #endif
0155 
0156 // HP aCC
0157 #if defined (__HP_aCC)
0158 #if !defined(HAVE_LONG_LONG)
0159 #define HAVE_LONG_LONG 1
0160 #endif
0161 #endif
0162 
0163 // Metrowerks CodeWarrior
0164 #if defined (__MWERKS__)
0165 #if __option(bool)
0166 #define q4_BOOL 1       // bool datatype is optionally supported
0167 // undef, these conflict with c4_Storage::c4_Storage overloading
0168 #undef bool
0169 #undef true
0170 #undef false
0171 #endif
0172 #endif
0173 
0174 // Microsoft Visual C++
0175 #if defined (_MSC_VER)
0176 // MSVC 5.0 supports the bool datatype, MSVC 4.x has no namespaces
0177 #if _MSC_VER >= 1100
0178 #define q4_BOOL 1
0179 #define LONG_LONG __int64
0180 #else
0181 #define q4_NO_NS 1
0182 #endif
0183 
0184 // a kludge to avoid having to use ugly DLL exprt defs in this header
0185 #pragma warning(disable: 4273) // inconsistent dll linkage
0186 #endif // _MSC_VER
0187 
0188 //---------------------------------------------------------------------------
0189 // Other definitions needed by the public Metakit library header files
0190 
0191 #if !defined(q4_BOOL) && !defined(q4_STD)         // define a bool datatype
0192 #define false 0
0193 #define true 1
0194 #define bool int
0195 #endif
0196 
0197 #if defined(q4_KITDLL)                   // add declaration specifiers
0198 #include "mk4dll.h"
0199 #endif
0200 
0201 #if defined(q4_INLINE)                   // enable inline expansion
0202 #define d4_inline inline
0203 #else
0204 #define d4_inline
0205 #endif
0206 
0207 using t4_byte = unsigned char; // create typedefs for t4_byte, etc.
0208 
0209 #if defined(q4_LONG64)
0210 using t4_i32 = int; // if longs are 64b, then int must be 32b
0211 #else
0212 typedef long t4_i32;            // if longs aren't 64b, then they are 32b
0213 #endif
0214 
0215 #if defined(q4_LONG64)           // choose a way to represent 64b integers
0216 using t4_i64 = long;
0217 #elif defined (LONG_LONG)
0218 typedef LONG_LONG t4_i64;
0219 #elif defined(HAVE_LONG_LONG)
0220 typedef long long t4_i64;
0221 #else
0222 struct t4_i64 {
0223     long l1;
0224     long l2;
0225 };
0226 bool operator==(const t4_i64 a_, const t4_i64 b_);
0227 bool operator<(const t4_i64 a_, const t4_i64 b_);
0228 #endif
0229 
0230 //---------------------------------------------------------------------------
0231 
0232 class c4_View
0233 {
0234 protected:
0235     c4_Sequence *_seq;
0236 
0237 public:
0238     /* Construction / destruction / assignment */
0239     c4_View(c4_Sequence * = nullptr);
0240     c4_View(c4_CustomViewer *);
0241     c4_View(c4_Stream *);
0242     c4_View(const c4_Property &property_);
0243     c4_View(const c4_View &);
0244     ~c4_View();
0245 
0246     c4_View &operator=(const c4_View &);
0247     c4_Persist *Persist() const; // added 16-11-2000 to simplify c4_Storage
0248 
0249     /* Getting / setting the number of rows */
0250     int GetSize() const;
0251     void SetSize(int, int = -1);
0252 
0253     void RemoveAll();
0254 
0255     /*: Getting / setting individual elements */
0256     c4_RowRef GetAt(int) const;
0257     c4_RowRef operator[](int) const;
0258 
0259     void SetAt(int, const c4_RowRef &);
0260     c4_RowRef ElementAt(int);
0261 
0262     bool GetItem(int, int, c4_Bytes &) const;
0263     void SetItem(int, int, const c4_Bytes &) const;
0264 
0265     /* These can increase the number of rows */
0266     void SetAtGrow(int, const c4_RowRef &);
0267     int Add(const c4_RowRef &);
0268 
0269     /* Insertion / deletion of rows */
0270     void InsertAt(int, const c4_RowRef &, int = 1);
0271     void RemoveAt(int, int = 1);
0272     void InsertAt(int, const c4_View &);
0273 
0274     bool IsCompatibleWith(const c4_View &) const;
0275     void RelocateRows(int, int, c4_View &, int);
0276 
0277     /* Dealing with the properties of this view */
0278     int NumProperties() const;
0279     const c4_Property &NthProperty(int) const;
0280     int FindProperty(int);
0281     int FindPropIndexByName(const char *) const;
0282     c4_View Duplicate() const;
0283     c4_View Clone() const;
0284     int AddProperty(const c4_Property &);
0285     c4_View operator,(const c4_Property &) const;
0286 
0287     const char *Description() const;
0288 
0289     /* Derived views */
0290     c4_View Sort() const;
0291     c4_View SortOn(const c4_View &) const;
0292     c4_View SortOnReverse(const c4_View &, const c4_View &) const;
0293 
0294     c4_View Select(const c4_RowRef &) const;
0295     c4_View SelectRange(const c4_RowRef &, const c4_RowRef &) const;
0296 
0297     c4_View Project(const c4_View &) const;
0298     c4_View ProjectWithout(const c4_View &) const;
0299 
0300     int GetIndexOf(const c4_RowRef &) const;
0301     int RestrictSearch(const c4_RowRef &, int &, int &);
0302 
0303     /* Custom views */
0304     c4_View Slice(int, int = -1, int = 1) const;
0305     c4_View Product(const c4_View &) const;
0306     c4_View RemapWith(const c4_View &) const;
0307     c4_View Pair(const c4_View &) const;
0308     c4_View Concat(const c4_View &) const;
0309     c4_View Rename(const c4_Property &, const c4_Property &) const;
0310 
0311     c4_View GroupBy(const c4_View &, const c4_ViewProp &) const;
0312     c4_View Counts(const c4_View &, const c4_IntProp &) const;
0313     c4_View Unique() const;
0314 
0315     c4_View Union(const c4_View &) const;
0316     c4_View Intersect(const c4_View &) const;
0317     c4_View Different(const c4_View &) const;
0318     c4_View Minus(const c4_View &) const;
0319 
0320     c4_View JoinProp(const c4_ViewProp &, bool = false) const;
0321     c4_View Join(const c4_View &, const c4_View &, bool = false) const;
0322 
0323     c4_View ReadOnly() const;
0324     c4_View Hash(const c4_View &, int = 1) const;
0325     c4_View Blocked() const;
0326     c4_View Ordered(int = 1) const;
0327     c4_View Indexed(const c4_View &, const c4_View &, bool = false) const;
0328 
0329     /* Searching */
0330     int Find(const c4_RowRef &, int = 0) const;
0331     int Search(const c4_RowRef &) const;
0332     int Locate(const c4_RowRef &, int * = nullptr) const;
0333 
0334     /* Comparing view contents */
0335     int Compare(const c4_View &) const;
0336 
0337     friend bool operator==(const c4_View &, const c4_View &);
0338     friend bool operator!=(const c4_View &, const c4_View &);
0339     friend bool operator<(const c4_View &, const c4_View &);
0340     friend bool operator>(const c4_View &, const c4_View &);
0341     friend bool operator<=(const c4_View &, const c4_View &);
0342     friend bool operator>=(const c4_View &, const c4_View &);
0343 
0344 protected:
0345     void _IncSeqRef();
0346     void _DecSeqRef();
0347 
0348     /// View references are allowed to peek inside view objects
0349     friend class c4_ViewRef;
0350 
0351     // DROPPED: Structure() const;
0352     // DROPPED: Description(const c4_View& view_);
0353 };
0354 
0355 //---------------------------------------------------------------------------
0356 
0357 #if defined(os_aix) && defined(compiler_ibmcxx) && (compiler_ibmcxx > 500)
0358 bool operator==(const c4_RowRef &a_, const c4_RowRef &b_);
0359 bool operator!=(const c4_RowRef &a_, const c4_RowRef &b_);
0360 bool operator<=(const c4_RowRef &a_, const c4_RowRef &b_);
0361 bool operator>=(const c4_RowRef &a_, const c4_RowRef &b_);
0362 bool operator>(const c4_RowRef &a_, const c4_RowRef &b_);
0363 bool operator<(const c4_RowRef &a_, const c4_RowRef &b_);
0364 #endif
0365 
0366 class c4_Cursor
0367 {
0368 public:
0369     /// Pointer to the sequence
0370     c4_Sequence *_seq;
0371     /// Current index into the sequence
0372     int _index;
0373 
0374     /* Construction / destruction / dereferencing */
0375     /// Construct a new cursor
0376     c4_Cursor(c4_Sequence &, int);
0377 
0378     /// Dereference this cursor to "almost" a row
0379     c4_RowRef operator*() const;
0380 
0381     /// This is the same as *(cursor + offset)
0382     c4_RowRef operator[](int) const;
0383 
0384     /* Stepping the iterator forwards / backwards */
0385     /// Pre-increment the cursor
0386     c4_Cursor &operator++();
0387     /// Post-increment the cursor
0388     c4_Cursor operator++(int);
0389     /// Pre-decrement the cursor
0390     c4_Cursor &operator--();
0391     /// Post-decrement the cursor
0392     c4_Cursor operator--(int);
0393 
0394     /// Advance by a given offset
0395     c4_Cursor &operator+=(int);
0396     /// Back up by a given offset
0397     c4_Cursor &operator-=(int);
0398 
0399     /// Subtract a specified offset
0400     c4_Cursor operator-(int) const;
0401     /// Return the distance between two cursors
0402     int operator-(c4_Cursor) const;
0403 
0404     /// Add specified offset
0405     friend c4_Cursor operator+(c4_Cursor, int);
0406     /// Add specified offset to cursor
0407     friend c4_Cursor operator+(int, c4_Cursor);
0408 
0409     /* Comparing row positions */
0410     /// Return true if both cursors are equal
0411     friend bool operator==(c4_Cursor, c4_Cursor);
0412     /// Return true if both cursors are not equal
0413     friend bool operator!=(c4_Cursor, c4_Cursor);
0414     /// True if first cursor is less than second cursor
0415     friend bool operator<(c4_Cursor, c4_Cursor);
0416     /// True if first cursor is greater than second cursor
0417     friend bool operator>(c4_Cursor, c4_Cursor);
0418     /// True if first cursor is less or equal to second cursor
0419     friend bool operator<=(c4_Cursor, c4_Cursor);
0420     /// True if first cursor is greater or equal to second cursor
0421     friend bool operator>=(c4_Cursor, c4_Cursor);
0422 
0423     /* Comparing row contents */
0424     /// Return true if the contents of both rows are equal
0425     friend bool operator==(const c4_RowRef &, const c4_RowRef &);
0426     /// Return true if the contents of both rows are not equal
0427     friend bool operator!=(const c4_RowRef &, const c4_RowRef &);
0428     /// True if first row is less than second row
0429     friend bool operator<(const c4_RowRef &, const c4_RowRef &);
0430     /// True if first row is greater than second row
0431     friend bool operator>(const c4_RowRef &, const c4_RowRef &);
0432     /// True if first row is less or equal to second row
0433     friend bool operator<=(const c4_RowRef &, const c4_RowRef &);
0434     /// True if first row is greater or equal to second row
0435     friend bool operator>=(const c4_RowRef &, const c4_RowRef &);
0436 };
0437 
0438 //---------------------------------------------------------------------------
0439 
0440 class c4_RowRef
0441 {
0442     /// A row reference is a cursor in disguise
0443     c4_Cursor _cursor;
0444 
0445 public:
0446     /* General operations */
0447     /// Assign the value of another row to this one
0448     c4_RowRef operator=(const c4_RowRef &);
0449     /// Return the cursor associated to this row
0450     c4_Cursor operator&() const;
0451     /// Return the underlying container view
0452     c4_View Container() const;
0453 
0454 protected:
0455     /// Constructor, not for general use
0456     c4_RowRef(c4_Cursor);
0457 
0458     friend class c4_Cursor;
0459     friend class c4_Row;
0460 };
0461 
0462 //---------------------------------------------------------------------------
0463 /// An entry in a collection with copy semantics.
0464 //
0465 //  Rows can exist by themselves and as contents of views.  Row assignment
0466 //  implies that a copy of the contents of the originating row is made.
0467 //
0468 //  A row is implemented as an unattached view with exactly one element.
0469 
0470 class c4_Row : public c4_RowRef
0471 {
0472 public:
0473     /// Construct a row with no properties
0474     c4_Row();
0475     /// Construct a row from another one
0476     c4_Row(const c4_Row &);
0477     /// Construct a row copy from a row reference
0478     c4_Row(const c4_RowRef &);
0479     /// Destructor
0480     ~c4_Row();
0481 
0482     /// Assign a copy of another row to this one
0483     c4_Row &operator=(const c4_Row &);
0484     /// Copy another row to this one
0485     c4_Row &operator=(const c4_RowRef &);
0486 
0487     /// Add all properties and values into this row
0488     void ConcatRow(const c4_RowRef &);
0489     /// Return a new row which is the concatenation of two others
0490     friend c4_Row operator+(const c4_RowRef &, const c4_RowRef &);
0491 
0492 private:
0493     static c4_Cursor Allocate();
0494     static void Release(c4_Cursor);
0495 };
0496 
0497 //---------------------------------------------------------------------------
0498 
0499 class c4_Bytes
0500 {
0501     union {
0502         t4_byte _buffer [16];
0503         double _aligner; // on a Sparc, the int below wasn't enough...
0504     };
0505 
0506     t4_byte *_contents;
0507     int _size;
0508     bool _copy;
0509 
0510 public:
0511     c4_Bytes();
0512     c4_Bytes(const void *, int);
0513     c4_Bytes(const void *, int, bool);
0514     c4_Bytes(const c4_Bytes &);
0515     ~c4_Bytes();
0516 
0517     c4_Bytes &operator=(const c4_Bytes &);
0518     void Swap(c4_Bytes &);
0519 
0520     int Size() const;
0521     const t4_byte *Contents() const;
0522 
0523     t4_byte *SetBuffer(int);
0524     t4_byte *SetBufferClear(int);
0525 
0526     friend bool operator==(const c4_Bytes &, const c4_Bytes &);
0527     friend bool operator!=(const c4_Bytes &, const c4_Bytes &);
0528 
0529 private:
0530     void _MakeCopy();
0531     void _LoseCopy();
0532 };
0533 
0534 //---------------------------------------------------------------------------
0535 
0536 class c4_Storage : public c4_View
0537 {
0538 public:
0539     /// Construct streaming-only storage object
0540     c4_Storage();
0541     /// Construct a storage using the specified strategy handler
0542     c4_Storage(c4_Strategy &, bool = false, int = 1);
0543     /// Construct a storage object, keeping the current structure
0544     c4_Storage(const char *, int);
0545     /// Reconstruct a storage object from a suitable view
0546     c4_Storage(const c4_View &);
0547     /// Destructor, usually closes file, but does not commit by default
0548     ~c4_Storage();
0549 
0550     void SetStructure(const char *);
0551     bool AutoCommit(bool = true);
0552     c4_Strategy &Strategy() const;
0553     const char *Description(const char * = nullptr);
0554 
0555     bool SetAside(c4_Storage &);
0556     c4_Storage *GetAside() const;
0557 
0558     bool Commit(bool = false);
0559     bool Rollback(bool = false);
0560 
0561     c4_ViewRef View(const char *);
0562     c4_View GetAs(const char *);
0563 
0564     bool LoadFrom(c4_Stream &);
0565     void SaveTo(c4_Stream &);
0566 
0567     t4_i32 FreeSpace(t4_i32 *bytes_ = nullptr);
0568 
0569     //DROPPED: c4_Storage (const char* filename_, const char* description_);
0570     //DROPPED: c4_View Store(const char* name_, const c4_View& view_);
0571     //DROPPED: c4_HandlerSeq& RootTable() const;
0572     //DROPPED: c4_RowRef xContents() const;
0573 
0574 private:
0575     void Initialize(c4_Strategy &, bool, int);
0576 };
0577 
0578 //---------------------------------------------------------------------------
0579 
0580 class c4_Property
0581 {
0582     short _id;
0583     char _type;
0584 
0585 public:
0586     /// Construct a new property with the give type and id
0587     c4_Property(char, int);
0588     /// Construct a new property with the give type and name
0589     c4_Property(char, const char *);
0590     ~c4_Property();
0591 
0592     c4_Property(const c4_Property &);
0593     void operator=(const c4_Property &);
0594 
0595     const char *Name() const;
0596     char Type() const;
0597 
0598     int GetId() const;
0599 
0600     c4_Reference operator()(const c4_RowRef &) const;
0601 
0602     void Refs(int) const;
0603 
0604     c4_View operator,(const c4_Property &) const;
0605 
0606     static void CleanupInternalData();
0607 };
0608 
0609 /// Integer properties.
0610 class c4_IntProp : public c4_Property
0611 {
0612 public:
0613     /// Construct a new property
0614     c4_IntProp(const char *);
0615     /// Destructor
0616     ~c4_IntProp();
0617 
0618     /// Get or set an integer property in a row
0619     c4_IntRef operator()(const c4_RowRef &) const;
0620     /// Get an integer property in a row
0621     t4_i32 Get(const c4_RowRef &) const;
0622     /// Set an integer property in a row
0623     void Set(const c4_RowRef &, t4_i32) const;
0624 
0625     /// Creates a row with one integer, shorthand for AsRow.
0626     c4_Row operator[](t4_i32) const;
0627     /// Creates a row with one integer.
0628     c4_Row AsRow(t4_i32) const;
0629 };
0630 
0631 #if !defined(q4_TINY)
0632 
0633 /// Long int properties.
0634 class c4_LongProp : public c4_Property
0635 {
0636 public:
0637     /// Construct a new property
0638     c4_LongProp(const char *);
0639     /// Destructor
0640     ~c4_LongProp();
0641 
0642     /// Get or set a long int property in a row
0643     c4_LongRef operator()(const c4_RowRef &) const;
0644     /// Get a long int property in a row
0645     t4_i64 Get(const c4_RowRef &) const;
0646     /// Set a long int property in a row
0647     void Set(const c4_RowRef &, t4_i64) const;
0648 
0649     /// Creates a row with one long int, shorthand for AsRow.
0650     c4_Row operator[](t4_i64) const;
0651     /// Creates a row with one long int.
0652     c4_Row AsRow(t4_i64) const;
0653 };
0654 
0655 /// Floating point properties.
0656 class c4_FloatProp : public c4_Property
0657 {
0658 public:
0659     /// Construct a new property
0660     c4_FloatProp(const char *);
0661     /// Destructor
0662     ~c4_FloatProp();
0663 
0664     /// Get or set a floating point property in a row
0665     c4_FloatRef operator()(const c4_RowRef &) const;
0666     /// Get a floating point property in a row
0667     double Get(const c4_RowRef &) const;
0668     /// Set a floating point property in a row
0669     void Set(const c4_RowRef &, double) const;
0670 
0671     /// Create a row with one floating point value, shorthand for AsRow
0672     c4_Row operator[](double) const;
0673     /// Create a row with one floating point value
0674     c4_Row AsRow(double) const;
0675 };
0676 
0677 /// Double precision properties.
0678 class c4_DoubleProp : public c4_Property
0679 {
0680 public:
0681     /// Construct a new property.
0682     c4_DoubleProp(const char *);
0683     /// Destructor
0684     ~c4_DoubleProp();
0685 
0686     /// Get or set a double precision property in a row
0687     c4_DoubleRef operator()(const c4_RowRef &) const;
0688     /// Get a double precision property in a row
0689     double Get(const c4_RowRef &) const;
0690     /// Set a double precision property in a row
0691     void Set(const c4_RowRef &, double) const;
0692 
0693     /// Create a row with one double precision value, shorthand for AsRow
0694     c4_Row operator[](double) const;
0695     /// Create a row with one double precision value
0696     c4_Row AsRow(double) const;
0697 };
0698 #endif // !q4_TINY
0699 
0700 /// String properties.
0701 class c4_StringProp : public c4_Property
0702 {
0703 public:
0704     /// Construct a new property
0705     c4_StringProp(const char *);
0706     /// Destructor
0707     ~c4_StringProp();
0708 
0709     /// Get or set a string property in a row
0710     c4_StringRef operator()(const c4_RowRef &) const;
0711     /// Get a string property in a row
0712     const char *Get(const c4_RowRef &) const;
0713     /// Set a string property in a row
0714     void Set(const c4_RowRef &, const char *) const;
0715 
0716     /// Create a row with one string, shorthand for AsRow
0717     c4_Row operator[](const char *) const;
0718     /// Create a row with one string
0719     c4_Row AsRow(const char *) const;
0720 };
0721 
0722 /// Binary properties.
0723 class c4_BytesProp : public c4_Property
0724 {
0725 public:
0726     /// Construct a new property
0727     c4_BytesProp(const char *);
0728     /// Destructor
0729     ~c4_BytesProp();
0730 
0731     /// Get or set a bytes property in a row
0732     c4_BytesRef operator()(const c4_RowRef &) const;
0733     /// Get a bytes property in a row
0734     c4_Bytes Get(const c4_RowRef &) const;
0735     /// Set a bytes property in a row
0736     void Set(const c4_RowRef &, const c4_Bytes &) const;
0737 
0738     /// Create a row with one bytes object, shorthand for AsRow
0739     c4_Row operator[](const c4_Bytes &) const;
0740     /// Create a row with one bytes object
0741     c4_Row AsRow(const c4_Bytes &) const;
0742 };
0743 
0744 /// View properties.
0745 class c4_ViewProp : public c4_Property
0746 {
0747 public:
0748     /// Construct a new property
0749     c4_ViewProp(const char *);
0750     /// Destructor
0751     ~c4_ViewProp();
0752 
0753     /// Get or set a view property in a row
0754     c4_ViewRef operator()(const c4_RowRef &) const;
0755     /// Get a view property in a row
0756     c4_View Get(const c4_RowRef &) const;
0757     /// Set a view property in a row
0758     void Set(const c4_RowRef &, const c4_View &) const;
0759 
0760     /// Create a row with one view, shorthand for AsRow
0761     c4_Row operator[](const c4_View &) const;
0762     /// Create a row with one view
0763     c4_Row AsRow(const c4_View &) const;
0764 };
0765 
0766 //---------------------------------------------------------------------------
0767 
0768 class c4_CustomViewer
0769 {
0770 protected:
0771     /// Constructor, must be overridden in derived class
0772     c4_CustomViewer();
0773 public:
0774     /// Destructor
0775     virtual ~c4_CustomViewer();
0776 
0777     /// Return the structure of this view (initialization, called once)
0778     virtual c4_View GetTemplate() = 0;
0779     /// Return the number of rows in this view
0780     virtual int GetSize() = 0;
0781     int Lookup(const c4_RowRef &, int &);
0782     virtual int Lookup(c4_Cursor, int &);
0783     /// Fetch one data item, return it as a generic data value
0784     virtual bool GetItem(int, int, c4_Bytes &) = 0;
0785     virtual bool SetItem(int, int, const c4_Bytes &);
0786     bool InsertRows(int, const c4_RowRef &, int = 1);
0787     virtual bool InsertRows(int, c4_Cursor, int = 1);
0788     virtual bool RemoveRows(int, int = 1);
0789 };
0790 
0791 //---------------------------------------------------------------------------
0792 /// A stream is a virtual helper class to serialize in binary form.
0793 
0794 class c4_Stream
0795 {
0796 public:
0797     virtual ~c4_Stream();
0798 
0799     /// Fetch some bytes sequentially
0800     virtual int Read(void *, int) = 0;
0801     /// Store some bytes sequentially
0802     virtual bool Write(const void *, int) = 0;
0803 };
0804 
0805 //---------------------------------------------------------------------------
0806 /// A strategy encapsulates code dealing with the I/O system interface.
0807 
0808 class c4_Strategy
0809 {
0810 public:
0811     c4_Strategy();
0812     virtual ~c4_Strategy();
0813 
0814     virtual bool IsValid() const;
0815     virtual int DataRead(t4_i32, void *, int);
0816     virtual void DataWrite(t4_i32, const void *, int);
0817     virtual void DataCommit(t4_i32);
0818     virtual void ResetFileMapping();
0819     virtual t4_i32 FileSize();
0820     virtual t4_i32 FreshGeneration();
0821 
0822     void SetBase(t4_i32);
0823     t4_i32 EndOfData(t4_i32 = -1);
0824 
0825     /// True if the storage format is not native (default is false)
0826     bool _bytesFlipped;
0827     /// Error code of last failed I/O operation, zero if I/O was ok
0828     int _failure;
0829     /// First byte in file mapping, zero if not active
0830     const t4_byte *_mapStart;
0831     /// Number of bytes filled with active data
0832     t4_i32 _dataSize;
0833     /// All file positions are relative to this offset
0834     t4_i32 _baseOffset;
0835     /// The root position of the shallow tree walks
0836     t4_i32 _rootPos;
0837     /// The size of the root column
0838     t4_i32 _rootLen;
0839 };
0840 
0841 //---------------------------------------------------------------------------
0842 /// A sequence is an abstract base class for views on ranges of records.
0843 //
0844 //  Sequences represent arrays of rows (or indexed collections / tables).
0845 //  Insertion and removal of entries is allowed, but could take linear time.
0846 //  A reference count is maintained to decide when the object should go away.
0847 
0848 class c4_Sequence
0849 {
0850     /// Reference count
0851     int _refCount;
0852     /// Pointer to dependency list, or null if nothing depends on this
0853     c4_Dependencies *_dependencies;
0854 
0855 protected:
0856     /// Optimization: cached property index
0857     int _propertyLimit;
0858     /// Optimization: property map for faster access
0859     short *_propertyMap; // see c4_HandlerSeq::Reset()
0860     /// allocated on first use by c4_Sequence::Buffer()
0861     c4_Bytes *_tempBuf;
0862 
0863 public:
0864     /* General */
0865     /// Abstract constructor
0866     c4_Sequence();
0867 
0868     virtual int Compare(int, c4_Cursor) const;
0869     virtual bool RestrictSearch(c4_Cursor, int &, int &);
0870     void SetAt(int, c4_Cursor);
0871     virtual int RemapIndex(int, const c4_Sequence *) const;
0872 
0873     /* Reference counting */
0874     void IncRef();
0875     void DecRef();
0876     int NumRefs() const;
0877 
0878     /* Adding / removing rows */
0879     /// Return the current number of rows
0880     virtual int NumRows() const = 0;
0881     void Resize(int, int = -1);
0882 
0883     virtual void InsertAt(int, c4_Cursor, int = 1);
0884     virtual void RemoveAt(int, int = 1);
0885     virtual void Move(int, int);
0886 
0887     /* Properties */
0888     int NthPropId(int) const;
0889     int PropIndex(int);
0890     int PropIndex(const c4_Property &);
0891 
0892     /// Return the number of data handlers in this sequence
0893     virtual int NumHandlers() const = 0;
0894     /// Return a reference to the N-th handler in this sequence
0895     virtual c4_Handler &NthHandler(int) const = 0;
0896     /// Return the context of the N-th handler in this sequence
0897     virtual const c4_Sequence *HandlerContext(int) const = 0;
0898     /// Add the specified data handler to this sequence
0899     virtual int AddHandler(c4_Handler *) = 0;
0900     /// Create a handler of the appropriate type
0901     virtual c4_Handler *CreateHandler(const c4_Property &) = 0;
0902 
0903     virtual const char *Description();
0904 
0905     /* Element access */
0906     /// Return width of specified data item
0907     virtual int ItemSize(int, int);
0908     /// Retrieve one data item from this sequence
0909     virtual bool Get(int, int, c4_Bytes &);
0910     /// Store a data item into this sequence
0911     virtual void Set(int, const c4_Property &, const c4_Bytes &);
0912 
0913     /* Dependency notification */
0914     void Attach(c4_Sequence *);
0915     void Detach(c4_Sequence *);
0916     /// Return a pointer to the dependencies, or null
0917     c4_Dependencies *GetDependencies() const;
0918 
0919     virtual c4_Notifier *PreChange(c4_Notifier &);
0920     virtual void PostChange(c4_Notifier &);
0921 
0922     const char *UseTempBuffer(const char *);
0923 
0924 protected:
0925     virtual ~c4_Sequence();
0926 
0927     void ClearCache();
0928 
0929 public: //! for c4_Table::Sequence setup
0930     virtual void SetNumRows(int) = 0;
0931     virtual c4_Persist *Persist() const;
0932 
0933     c4_Bytes &Buffer();
0934 
0935 private:
0936     c4_Sequence(const c4_Sequence &) = delete; // not implemented
0937     void operator=(const c4_Sequence &) = delete; // not implemented
0938 };
0939 
0940 //---------------------------------------------------------------------------
0941 /// A reference is used to get or set typed data, using derived classes.
0942 //
0943 //  Objects of this class are only intended to be used as a temporary handle
0944 //  while getting and setting properties in a row.  They are normally only
0945 //  constructed as result of function overload operators: "property (row)".
0946 
0947 class c4_Reference
0948 {
0949 protected:
0950     /// The cursor which points to the data
0951     c4_Cursor _cursor;
0952     /// The property associated to this reference
0953     const c4_Property &_property;
0954 
0955 public:
0956     /// Constructor
0957     c4_Reference(const c4_RowRef &, const c4_Property &);
0958 
0959     /// Assignment of one data item
0960     c4_Reference &operator=(const c4_Reference &);
0961 
0962     /// Return width of the referenced data item
0963     int GetSize() const;
0964     /// Retrieve the value of the referenced data item
0965     bool GetData(c4_Bytes &) const;
0966     /// Store a value into the referenced data item
0967     void SetData(const c4_Bytes &) const;
0968 
0969     /// Return true if the contents of both references is equal
0970     friend bool operator==(const c4_Reference &, const c4_Reference &);
0971     /// Return true if the contents of both references is not equal
0972     friend bool operator!=(const c4_Reference &, const c4_Reference &);
0973 
0974 private:
0975     void operator&() const;             // not implemented
0976 };
0977 
0978 //---------------------------------------------------------------------------
0979 
0980 /// Used to get or set integer values.
0981 class c4_IntRef : public c4_Reference
0982 {
0983 public:
0984     /// Constructor
0985     c4_IntRef(const c4_Reference &);
0986     /// Get the value as integer
0987     operator t4_i32() const;
0988     /// Set the value to the specified integer
0989     c4_IntRef &operator=(t4_i32);
0990 };
0991 
0992 #if !defined(q4_TINY)
0993 
0994 /// Used to get or set long int values.
0995 class c4_LongRef : public c4_Reference
0996 {
0997 public:
0998     /// Constructor
0999     c4_LongRef(const c4_Reference &);
1000     /// Get the value as long int
1001     operator t4_i64() const;
1002     /// Set the value to the specified long int
1003     c4_LongRef &operator=(t4_i64);
1004 };
1005 
1006 /// Used to get or set floating point values.
1007 class c4_FloatRef : public c4_Reference
1008 {
1009 public:
1010     /// Constructor
1011     c4_FloatRef(const c4_Reference &);
1012     /// Get the value as floating point
1013     operator double() const;
1014     /// Set the value to the specified floating point
1015     c4_FloatRef &operator=(double);
1016 };
1017 
1018 /// Used to get or set double precision values.
1019 class c4_DoubleRef : public c4_Reference
1020 {
1021 public:
1022     /// Constructor
1023     c4_DoubleRef(const c4_Reference &);
1024     /// Get the value as floating point
1025     operator double() const;
1026     /// Set the value to the specified floating point
1027     c4_DoubleRef &operator=(double);
1028 };
1029 
1030 #endif // !q4_TINY
1031 
1032 /// Used to get or set binary object values.
1033 class c4_BytesRef : public c4_Reference
1034 {
1035 public:
1036     /// Constructor
1037     c4_BytesRef(const c4_Reference &);
1038     /// Get the value as binary object
1039     operator c4_Bytes() const;
1040     /// Set the value to the specified binary object
1041     c4_BytesRef &operator=(const c4_Bytes &);
1042 
1043     /// Fetch data from the memo field, up to end if length is zero
1044     c4_Bytes Access(t4_i32, int = 0, bool = false) const;
1045     /// Store data, resize by diff_ bytes, return true if successful
1046     bool Modify(const c4_Bytes &, t4_i32, int = 0) const;
1047 };
1048 
1049 /// Used to get or set string values.
1050 class c4_StringRef : public c4_Reference
1051 {
1052 public:
1053     /// Constructor
1054     c4_StringRef(const c4_Reference &);
1055     /// Get the value as string
1056     operator const char *() const;
1057     /// Set the value to the specified string
1058     c4_StringRef &operator=(const char *);
1059 };
1060 
1061 /// Used to get or set view values.
1062 class c4_ViewRef : public c4_Reference
1063 {
1064 public:
1065     /// Constructor
1066     c4_ViewRef(const c4_Reference &);
1067     /// Get the value as view
1068     operator c4_View() const;
1069     /// Set the value to the specified view
1070     c4_ViewRef &operator=(const c4_View &);
1071 };
1072 
1073 //---------------------------------------------------------------------------
1074 // Debug logging option, can generate log of changes for one/all properties
1075 
1076 #if defined(q4_LOGPROPMODS)
1077 FILE *f4_LogPropMods(FILE *fp_, int propId_);
1078 #else
1079 #define f4_LogPropMods(a, b) 0
1080 #endif
1081 
1082 //---------------------------------------------------------------------------
1083 
1084 #if defined(q4_INLINE)
1085 #include "mk4.inl"
1086 #endif
1087 
1088 //---------------------------------------------------------------------------
1089