& v); svector(const char *raw_cstr); svector(const std::string& str); svector(const char *raw_data, size_t dlen); ~svector(); void push_back(const char *e); void pop_back(); void pop_back(std::string& last); svector
& operator=(const char *raw_cstr) { assign(raw_cstr); return *this; }; svector
& operator=(const std::string& str) { return operator=(str.c_str()); }; svector
& operator=(const svector
& v); svector
& operator/=(const svector
& v); svector
operator/(const svector
& v) { svector
lhs(*this);
lhs /= v;
return lhs;
};
void assign(const char *raw_cstr) {
assign_raw_cstr(raw_cstr, Int2Type & rhs) const {
return (_len == rhs._len && memcmp(_data, rhs._data, _len) == 0);
};
const char *operator[](size_t idx) const {
return elem_at(idx, Int2Type ::svector()
: _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
_buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
_data(_data_buf), _data_dbuf(0)
{
_elems[0] = _data;
_data[0] = 0;
}
template ::svector(const svector & v)
: _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
_buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
_data(_data_buf), _data_dbuf(0)
{
_elems[0] = _data;
_data[0] = 0;
operator=(v);
}
template ::svector(const char *raw_cstr)
: _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
_buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
_data(_data_buf), _data_dbuf(0)
{
assign(raw_cstr);
}
template ::svector(const std::string& str)
: _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
_buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
_data(_data_buf), _data_dbuf(0)
{
assign(str.c_str());
}
template ::svector(const char *raw_data, size_t dlen)
: _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
_buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
_data(_data_buf), _data_dbuf(0)
{
assign(raw_data, dlen);
}
template ::~svector()
{
if (_elems_dbuf) {
delete [] _elems_dbuf;
}
if (_data_dbuf) {
delete [] _data_dbuf;
}
}
template ::push_back(const char *e)
{
size_t elen = strlen(e);
while ((_len + elen + 2) >= _buf_size) {
// make sure there's space for (data + SEP + e + 0)
grow_data();
}
char *start = _elems[_num_elems];
*start = ELEM_SEP;
memcpy(start + 1, e, elen + 1);
inc_num_elems();
_len += (elen + 1);
_elems[_num_elems] = start + 1 + elen;
}
template ::pop_back()
{
if (_num_elems == 0) {
return;
}
--_num_elems;
_len = _elems[_num_elems] - _data;
_data[_len] = 0;
}
template ::pop_back(std::string& last)
{
if (_num_elems == 0) {
return;
}
last = _elems[_num_elems - 1] + 1;
pop_back();
}
template &
svector ::operator=(const svector & v)
{
if (this == &v) {
return *this;
}
while (_buf_size < v._buf_size) {
grow_data();
}
if (_ebuf_size >= v._ebuf_size) {
_num_elems = v._num_elems;
} else {
_num_elems = 0;
while (_num_elems < v._num_elems) {
inc_num_elems();
}
}
_len = v._len;
memcpy(_data, v._data, _len + 1);
memcpy(_elems, v._elems, sizeof(char *) * (_num_elems + 1));
const char *o0 = _elems[0];
for (size_t i = 0; i <= _num_elems; i++) {
_elems[i] = _data + (_elems[i] - o0);
}
return *this;
}
template &
svector ::operator/=(const svector & v)
{
while ((_len + v._len + 1) >= _buf_size) {
// make sure there's space for (data + data + 0)
grow_data();
}
size_t v_num_elems = v._num_elems;
size_t olen = _len;
memcpy(_data + _len, v._data, v._len + 1);
_len += v._len;
for (size_t i = 1; i <= v_num_elems; i++) {
inc_num_elems();
_elems[_num_elems] = _data + olen + (v._elems[i] - v._data);
}
return *this;
}
template ::assign(const char *raw_data, size_t dlen)
{
_num_elems = 0;
_len = 0;
_elems[0] = _data;
if (dlen == 0 || (dlen == 1 && raw_data[0] == ELEM_SEP)) {
_data[0] = 0;
return;
}
while ((dlen + 2) >= _buf_size) {
// make sure there's space for (SEP + raw_data + 0)
grow_data();
}
_len = dlen;
if (raw_data[0] != ELEM_SEP) {
_data[0] = ELEM_SEP;
memcpy(_data + 1, raw_data, _len + 1);
++_len;
} else {
memcpy(_data, raw_data, _len + 1);
}
for (size_t i = 1; i < _len; i++) {
if (_data[i] == ELEM_SEP) {
inc_num_elems();
_elems[_num_elems] = &(_data[i]);
}
}
inc_num_elems();
_elems[_num_elems] = _data + _len;
}
template ::grow_data()
{
char *tmp = new char[_buf_size + STATIC_BUF_LEN];
if (!tmp) {
// doomed
exit(1);
}
memcpy(tmp, _data, _len + 1);
if (tmp != _data_dbuf) {
for (size_t i = 0; i <= _num_elems; i++) {
_elems[i] = tmp + (_elems[i] - _data);
}
}
if (_data_dbuf) {
delete [] _data_dbuf;
}
_data_dbuf = tmp;
_data = _data_dbuf;
_buf_size += STATIC_BUF_LEN;
}
template ::grow_elems()
{
char **tmp = new char *[_ebuf_size + STATIC_NUM_ELEMS];
if (!tmp) {
// doomed
exit(1);
}
memcpy(tmp, _elems, _ebuf_size * sizeof(char *));
if (_elems_dbuf) {
delete [] _elems_dbuf;
}
_elems_dbuf = tmp;
_elems = _elems_dbuf;
_ebuf_size += STATIC_NUM_ELEMS;
}
} // end namespace cstore
#endif /* _SVECTOR_HPP_ */