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