// column.h -- // $Id$ // This is part of Metakit, see http://www.equi4.com/metakit/ /** @file * Definition of the column classes */ #ifndef __COLUMN_H__ #define __COLUMN_H__ ///////////////////////////////////////////////////////////////////////////// // Declarations in this file class c4_Column; // a column in a table class c4_ColIter; // an iterator over column data class c4_ColCache; // manages a cache for columns class c4_Persist; // not defined here class c4_Strategy; // not defined here ///////////////////////////////////////////////////////////////////////////// class c4_Column { c4_PtrArray _segments; t4_i32 _position; t4_i32 _size; c4_Persist* _persist; t4_i32 _gap; int _slack; bool _dirty; public: c4_Column (c4_Persist* persist_); //: Constructs a column using the specified persistence manager. ~c4_Column (); void SetBuffer(t4_i32); //: Allocate a new buffer of the specified size. c4_Persist* Persist() const; //: Returns persistence manager for this column, or zero. c4_Strategy& Strategy() const; //: Returns the associated strategy pointer. t4_i32 Position() const; //: Special access for the DUMP program. t4_i32 ColSize() const; //: Returns the number of bytes as stored on disk. bool IsDirty() const; //: Returns true if contents needs to be saved. void SetLocation(t4_i32, t4_i32); //: Sets the position and size of this column on file. void PullLocation(const t4_byte*& ptr_); //: Extract position and size of this column. int AvailAt(t4_i32 offset_) const; //: Returns number of bytes we can access at once. const t4_byte* LoadNow(t4_i32); //: Makes sure the data is loaded into memory. t4_byte* CopyNow(t4_i32); //: Makes sure a copy of the data is in memory. void Grow(t4_i32, t4_i32); //: Grows the buffer by inserting space. void Shrink(t4_i32, t4_i32); //: Shrinks the buffer by removing space. void SaveNow(c4_Strategy&, t4_i32 pos_); //: Save the buffer to file. const t4_byte* FetchBytes(t4_i32 pos_, int len_, c4_Bytes& buffer_, bool forceCopy_); //: Returns pointer to data, use buffer only if non-contiguous. void StoreBytes(t4_i32 pos_, const c4_Bytes& buffer_); //: Stores a copy of the buffer in the column. bool RequiresMap() const; void ReleaseAllSegments(); static t4_i32 PullValue(const t4_byte*& ptr_); static void PushValue(t4_byte*& ptr_, t4_i32 v_); void InsertData(t4_i32 index_, t4_i32 count_, bool clear_); void RemoveData(t4_i32 index_, t4_i32 count_); void RemoveGap(); enum { kSegBits = 12, kSegMax = 1 << kSegBits, kSegMask = kSegMax - 1 }; private: static int fSegIndex(t4_i32 offset_); static t4_i32 fSegOffset(int index_); static int fSegRest(t4_i32 offset_); bool UsesMap(const t4_byte*) const; bool IsMapped() const; void ReleaseSegment(int); void SetupSegments(); void Validate() const; void FinishSlack(); void MoveGapUp(t4_i32 pos_); void MoveGapDown(t4_i32 pos_); void MoveGapTo(t4_i32 pos_); t4_byte* CopyData(t4_i32, t4_i32, int); }; ///////////////////////////////////////////////////////////////////////////// class c4_ColOfInts : public c4_Column { public: c4_ColOfInts (c4_Persist* persist_, int width_ =sizeof (t4_i32)); int RowCount() const; void SetRowCount(int numRows_); void FlipBytes(); int ItemSize(int index_); const void* Get(int index_, int& length_); void Set(int index_, const c4_Bytes& buf_); t4_i32 GetInt(int index_); void SetInt(int index_, t4_i32 value_); void Insert(int index_, const c4_Bytes& buf_, int count_); void Remove(int index_, int count_); static int CalcAccessWidth(int numRows_, t4_i32 colSize_); void SetAccessWidth(int bits_); void FixSize(bool fudge_); void ForceFlip(); static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); private: typedef void (c4_ColOfInts::*tGetter) (int); typedef bool (c4_ColOfInts::*tSetter) (int, const t4_byte*); void Get_0b(int index_); void Get_1b(int index_); void Get_2b(int index_); void Get_4b(int index_); void Get_8i(int index_); void Get_16i(int index_); void Get_16r(int index_); void Get_32i(int index_); void Get_32r(int index_); void Get_64i(int index_); void Get_64r(int index_); bool Set_0b(int index_, const t4_byte* item_); bool Set_1b(int index_, const t4_byte* item_); bool Set_2b(int index_, const t4_byte* item_); bool Set_4b(int index_, const t4_byte* item_); bool Set_8i(int index_, const t4_byte* item_); bool Set_16i(int index_, const t4_byte* item_); bool Set_16r(int index_, const t4_byte* item_); bool Set_32i(int index_, const t4_byte* item_); bool Set_32r(int index_, const t4_byte* item_); bool Set_64i(int index_, const t4_byte* item_); bool Set_64r(int index_, const t4_byte* item_); void ResizeData(int index_, int count_, bool clear_ =false); tGetter _getter; tSetter _setter; union { t4_byte _item[8]; // holds temp result (careful with tqalignment!) double _aligner; // needed for SPARC }; int _currWidth; // number of bits used for one entry (0..64) int _dataWidth; // number of bytes used for passing a value along int _numRows; bool _mustFlip; }; ///////////////////////////////////////////////////////////////////////////// class c4_ColIter { c4_Column& _column; t4_i32 _limit; t4_i32 _pos; int _len; const t4_byte* _ptr; public: c4_ColIter (c4_Column& col_, t4_i32 offset_, t4_i32 limit_); // ~c4_ColIter (); bool Next(); bool Next(int max_); const t4_byte* BufLoad() const; t4_byte* BufSave(); int BufLen() const; }; ///////////////////////////////////////////////////////////////////////////// #if q4_INLINE #include "column.inl" #endif ///////////////////////////////////////////////////////////////////////////// #endif