/// Insert one or more rows into this sequence void c4_Sequence::InsertAt(int index_, c4_Cursor newElem_, int count_) { d4_assert(newElem_._seq != 0); c4_Notifier change(this); if (GetDependencies()) { change.StartInsertAt(index_, newElem_, count_); } SetNumRows(NumRows() + count_); c4_Bytes data; for (int i = 0; i < newElem_._seq->NumHandlers(); ++i) { c4_Handler &h = newElem_._seq->NthHandler(i); // added 06-12-1999 to do index remapping for derived seq's const c4_Sequence *hc = newElem_._seq->HandlerContext(i); int ri = newElem_._seq->RemapIndex(newElem_._index, hc); int colNum = PropIndex(h.Property()); d4_assert(colNum >= 0); if (h.Property().Type() == 'V') { // If inserting from self: Make sure we get a copy of the bytes, // so we don't get an invalid pointer if the memory get realloc'ed h.GetBytes(ri, data, newElem_._seq == this); // special treatment for subviews, insert empty, then overwrite // changed 19990904 - probably fixes a long-standing limitation c4_Bytes temp; h.ClearBytes(temp); c4_Handler &h2 = NthHandler(colNum); h2.Insert(index_, temp, count_); for (int j = 0; j < count_; ++j) { h2.Set(index_ + j, data); } } else { h.GetBytes(ri, data); NthHandler(colNum).Insert(index_, data, count_); } } // if number of props in dest is larger after adding, clear the rest // this way, new props get copied and undefined props get cleared if (newElem_._seq->NumHandlers() < NumHandlers()) { for (int j = 0; j < NumHandlers(); ++j) { c4_Handler &h = NthHandler(j); // if the property does not appear in the source if (newElem_._seq->PropIndex(h.PropId()) < 0) { h.ClearBytes(data); h.Insert(index_, data, count_); } } } }
c4_HandlerSeq::~c4_HandlerSeq() { const bool rootLevel = _parent == this; c4_Persist *pers = _persist; if (rootLevel && pers != 0) { pers->DoAutoCommit(); } DetachFromParent(); DetachFromStorage(true); for (int i = 0; i < NumHandlers(); ++i) { delete &NthHandler(i); } _handlers.SetSize(0); ClearCache(); if (rootLevel) { delete _field; d4_assert(pers != 0); delete pers; } }
void c4_HandlerSeq::DetachFromStorage(bool full_) { if (_persist != 0) { int limit = full_ ? 0 : NumFields(); // get rid of all handlers which might do I/O for (int c = NumHandlers(); --c >= 0;) { c4_Handler &h = NthHandler(c); // all nested fields are detached recursively if (IsNested(c)) for (int r = 0; r < NumRows(); ++r) if (h.HasSubview(r)) { SubEntry(c, r).DetachFromStorage(full_); } if (c >= limit) { if (h.IsPersistent()) { delete &h; _handlers.RemoveAt(c); ClearCache(); } } } if (full_) { //UnmappedAll(); _persist = 0; } } }
void c4_HandlerSeq::Prepare(const t4_byte **ptr_, bool selfDesc_) { if (ptr_ != 0) { d4_dbgdef(t4_i32 sias =)c4_Column::PullValue(*ptr_); d4_assert(sias == 0); // not yet if (selfDesc_) { t4_i32 n = c4_Column::PullValue(*ptr_); if (n > 0) { c4_String s = "[" + c4_String((const char *) * ptr_, n) + "]"; const char *desc = s; c4_Field *f = d4_new c4_Field(desc); d4_assert(! *desc); Restructure(*f, false); *ptr_ += n; } } int rows = (int)c4_Column::PullValue(*ptr_); if (rows > 0) { SetNumRows(rows); for (int i = 0; i < NumFields(); ++i) { NthHandler(i).Define(rows, ptr_); } } }
/// Move a row to another position void c4_Sequence::Move(int from_, int to_) { c4_Notifier change(this); if (GetDependencies()) change.StartMove(from_, to_); //! careful, this does no index remapping, wrong for derived seq's for (int i = 0; i < NumHandlers(); ++i) NthHandler(i).Move(from_, to_); }
/// Replace the contents of a specified row void c4_Sequence::SetAt(int index_, c4_Cursor newElem_) { d4_assert(newElem_._seq != 0); c4_Bytes data; c4_Notifier change(this); if(GetDependencies()) change.StartSetAt(index_, newElem_); for(int i = 0; i < newElem_._seq->NumHandlers(); ++i) { c4_Handler &h = newElem_._seq->NthHandler(i); // added 06-12-1999 to do index remapping for derived seq's const c4_Sequence *hc = newElem_._seq->HandlerContext(i); int ri = newElem_._seq->RemapIndex(newElem_._index, hc); h.GetBytes(ri, data); // Set(index_, cursor._seq->NthProperty(i), data); int colNum = PropIndex(h.Property()); d4_assert(colNum >= 0); NthHandler(colNum).Set(index_, data); } // if number of props in dest is larger after adding, clear the rest // this way, new props get copied and undefined props get cleared if(newElem_._seq->NumHandlers() < NumHandlers()) { for(int j = 0; j < NumHandlers(); ++j) { c4_Handler &h = NthHandler(j); // if the property does not appear in the source if(newElem_._seq->PropIndex(h.PropId()) < 0) { h.ClearBytes(data); h.Set(index_, data); } } } }
void c4_HandlerSeq::DetermineSpaceUsage() { for (int c = 0; c < NumFields(); ++c) if (IsNested(c)) { c4_Handler &h = NthHandler(c); for (int r = 0; r < NumRows(); ++r) if (h.HasSubview(r)) { SubEntry(c, r).DetermineSpaceUsage(); } } }
/// Remove one or more rows from this sequence void c4_Sequence::RemoveAt(int index_, int count_) { c4_Notifier change(this); if (GetDependencies()) change.StartRemoveAt(index_, count_); SetNumRows(NumRows() - count_); //! careful, this does no index remapping, wrong for derived seq's for (int i = 0; i < NumHandlers(); ++i) NthHandler(i).Remove(index_, count_); }
/// Compare the specified row with another one int c4_Sequence::Compare(int index_, c4_Cursor cursor_)const { d4_assert(cursor_._seq != 0); c4_Bytes data; for (int colNum = 0; colNum < NumHandlers(); ++colNum) { c4_Handler &h = NthHandler(colNum); const c4_Sequence *hc = HandlerContext(colNum); int i = RemapIndex(index_, hc); if (!cursor_._seq->Get(cursor_._index, h.PropId(), data)) h.ClearBytes(data); int f = h.Compare(i, data); if (f != 0) return f; } return 0; }
/// Return the id of the N-th property int c4_Sequence::NthPropId(int index_)const { return NthHandler(index_).PropId(); }
char c4_HandlerSeq::ColumnType(int index_)const { return NthHandler(index_).Property().Type(); }
void c4_HandlerSeq::Restructure(c4_Field &field_, bool remove_) { //d4_assert(_field != 0); // all nested fields must be set up, before we shuffle them around for (int k = 0; k < NumHandlers(); ++k) if (IsNested(k)) { c4_Handler &h = NthHandler(k); for (int n = 0; n < NumRows(); ++n) if (h.HasSubview(n)) { SubEntry(k, n); } } for (int i = 0; i < field_.NumSubFields(); ++i) { c4_Field &nf = field_.SubField(i); c4_Property prop(nf.Type(), nf.Name()); int n = PropIndex(prop.GetId()); if (n == i) { continue; } if (n < 0) { _handlers.InsertAt(i, f4_CreateFormat(prop, *this)); NthHandler(i).Define(NumRows(), 0); } else { // move the handler to the front d4_assert(n > i); _handlers.InsertAt(i, _handlers.GetAt(n)); _handlers.RemoveAt(++n); } ClearCache(); // we mess with the order of handler, keep clearing it d4_assert(PropIndex(prop.GetId()) == i); } c4_Field *ofld = _field; // special case if we're "restructuring a view out of persistence", see below _field = remove_ ? 0 : &field_; // let handler do additional init once all have been prepared //for (int n = 0; n < NumHandlers(); ++n) // NthHandler(n).Define(NumRows(), 0); const char *desc = "[]"; c4_Field temp(desc); // all nested fields are restructured recursively for (int j = 0; j < NumHandlers(); ++j) if (IsNested(j)) { c4_Handler &h = NthHandler(j); for (int n = 0; n < NumRows(); ++n) if (h.HasSubview(n)) { c4_HandlerSeq &seq = SubEntry(j, n); if (j < NumFields()) { seq.Restructure(field_.SubField(j), false); } else if (seq._field != 0) { seq.Restructure(temp, true); } } } if (_parent == this) { delete ofld; } // the root table owns its field structure tree }