Files
textmate/Frameworks/buffer/src/storage.cc
Allan Odgaard 9894969e67 Initial commit
2012-08-09 16:25:56 +02:00

124 lines
2.9 KiB
C++

#include "storage.h"
namespace ng
{
namespace detail
{
// ============
// = memory_t =
// ============
template <typename _InputIter>
memory_t::memory_t (_InputIter first, _InputIter last) : _offset(0)
{
_helper.reset(new helper_t(std::distance(first, last)));
std::copy(first, last, _helper->bytes());
}
template <typename _InputIter>
void memory_t::insert (size_t pos, _InputIter first, _InputIter last)
{
ASSERT_EQ(_offset + pos, _helper->size());
std::copy(first, last, _helper->bytes() + _offset + pos);
_helper->grow(std::distance(first, last));
}
// =============
// = storage_t =
// =============
static int comp_abs (size_t pos, size_t const& offset, size_t const& node) { return pos < offset ? -1 : (pos == offset ? 0 : +1); }
storage_t::tree_t::iterator storage_t::find_pos (size_t pos) const
{
auto it = _tree.upper_bound(pos, &comp_abs);
if(it != _tree.begin())
--it;
return it;
}
storage_t::tree_t::iterator storage_t::split_at (tree_t::iterator it, size_t pos)
{
ASSERT_LE(pos, it->key);
if(pos == 0)
return it;
else if(pos == it->key)
return ++it;
size_t suffixLen = it->key - pos;
memory_t suffix = it->value.subset(pos);
it->key = pos;
_tree.update_key(it);
return _tree.insert(++it, suffixLen, suffix);
}
void storage_t::insert (size_t pos, char const* data, size_t length)
{
ASSERT_LE(pos, size());
if(length == 0)
return;
auto it = find_pos(pos);
if(it != _tree.end() && it->offset < pos)
it = split_at(it, pos - it->offset);
if(it != _tree.begin())
{
auto tmp = it;
--tmp;
if(tmp->key == tmp->value.size() && length <= tmp->value.free())
{
tmp->value.insert(tmp->key, data, data + length);
tmp->key += length;
_tree.update_key(tmp);
return;
}
}
_tree.insert(it, length, memory_t(data, data + length));
}
void storage_t::erase (size_t first, size_t last)
{
ASSERT_LE(first, last); ASSERT_LE(last, size());
auto from = find_pos(first);
from = from != _tree.end() ? split_at(from, first - from->offset) : from;
auto to = find_pos(last);
to = to != _tree.end() ? split_at(to, last - to->offset) : to;
_tree.erase(from, to);
}
char storage_t::operator[] (size_t i) const
{
ASSERT_LE(i, size());
auto it = find_pos(i);
return it->value.bytes()[i - it->offset];
}
std::string storage_t::substr (size_t first, size_t last) const
{
ASSERT_LE(first, last); ASSERT_LE(last, size());
std::string res = "";
auto from = find_pos(first);
auto to = _tree.upper_bound(last, &comp_abs);
foreach(it, from, to)
{
size_t i = std::max(it->offset, first) - it->offset;
size_t j = std::min(it->offset + it->key, last) - it->offset;
res.insert(res.end(), it->value.bytes() + i, it->value.bytes() + j);
}
return res;
}
} /* detail */
} /* ng */