void c4_FormatB::Insert(int index_, const c4_Bytes& buf_, int count_) { d4_assert(count_ > 0); _recalc = true; int m = buf_.Size(); t4_i32 off = Offset(index_); _memos.InsertAt(index_, 0, count_); // insert the appropriate number of bytes t4_i32 n = count_ * (t4_i32) m; if (n > 0) { _data.Grow(off, n); // store as many copies as needed, but may have to do it in chunks int spos = 0; c4_ColIter iter (_data, off, off + n); while (iter.Next(m - spos)) { memcpy(iter.BufSave(), buf_.Contents() + spos, iter.BufLen()); spos += iter.BufLen(); if (spos >= m) spos = 0; } d4_assert(spos == 0); // must have copied an exact multiple of the data } // define offsets of the new entries _offsets.InsertAt(index_, 0, count_); d4_assert(_offsets.GetSize() <= _memos.GetSize() + 1); while (--count_ >= 0) { _offsets.SetAt(index_++, off); off += m; } d4_assert(index_ < _offsets.GetSize()); // adjust all following entries while (index_ < _offsets.GetSize()) _offsets.ElementAt(index_++) += n; d4_assert((t4_i32) _offsets.GetAt(index_ - 1) == _data.ColSize()); d4_assert(index_ <= _memos.GetSize() + 1); }
void c4_FormatS::Insert(int index_, const c4_Bytes& buf_, int count_) { d4_assert(count_ > 0); int m = buf_.Size(); if (--m >= 0) { d4_assert(buf_.Contents()[m] == 0); if (m == 0) { c4_FormatB::Insert(index_, c4_Bytes (), count_); return; } } c4_FormatB::Insert(index_, buf_, count_); }
void c4_FormatB::SetOne(int index_, const c4_Bytes &xbuf_, bool ignoreMemos_) { // this fixes bug in 2.4.0 when copying string from higher row // TODO: this fix is very conservative, figure out when to copy // (can probably look at pointer to see whether it's from us) int sz = xbuf_.Size(); c4_Bytes buf_(xbuf_.Contents(), sz, 0 < sz && sz <= c4_Column::kSegMax); c4_Column *cp = &_data; t4_i32 start = Offset(index_); int len = Offset(index_ + 1) - start; if (!ignoreMemos_ && _memos.GetAt(index_) != 0) len = ItemLenOffCol(index_, start, cp); int m = buf_.Size(); int n = m - len; if (n > 0) cp->Grow(start, n); else if (n < 0) cp->Shrink(start, - n); else if (m == 0) return ; // no size change and no contents _recalc = true; cp->StoreBytes(start, buf_); if (n && cp == &_data) { // if size has changed int k = _offsets.GetSize() - 1; // if filling in an empty entry at end: extend offsets first if (m > 0 && index_ >= k) { _offsets.InsertAt(k, _offsets.GetAt(k), index_ - k + 1); k = index_ + 1; d4_assert(k == _offsets.GetSize() - 1); } // adjust following entry offsets while (++index_ <= k) _offsets.ElementAt(index_) += n; } d4_assert((t4_i32)_offsets.GetAt(_offsets.GetSize() - 1) == _data.ColSize()); }
int c4_FormatB::DoCompare(const c4_Bytes &b1_, const c4_Bytes &b2_) { int n = b1_.Size(); if (n > b2_.Size()) n = b2_.Size(); int f = memcmp(b1_.Contents(), b2_.Contents(), n); return f ? f : b1_.Size() - b2_.Size(); }
int c4_FormatS::DoCompare(const c4_Bytes &b1_, const c4_Bytes &b2_) { c4_String v1((const char*)b1_.Contents(), b1_.Size()); c4_String v2((const char*)b2_.Contents(), b2_.Size()); return v1.CompareNoCase(v2); }