Implement compact_string with shared storage

This commit is contained in:
Arseny Kapoulkine 2015-05-01 22:47:53 -07:00
parent 3915f7b144
commit e4c539a869

View File

@ -892,14 +892,14 @@ PUGI__NS_BEGIN
uint16_t _data; uint16_t _data;
}; };
template <int header_offset> class compact_string_fat template <int header_offset, int base_offset> class compact_string
{ {
public: public:
compact_string_fat(): _data0(0), _data1(0), _data2(0) compact_string(): _data(0)
{ {
} }
void operator=(const compact_string_fat& rhs) void operator=(const compact_string& rhs)
{ {
*this = rhs + 0; *this = rhs + 0;
} }
@ -913,50 +913,59 @@ PUGI__NS_BEGIN
if (PUGI__UNLIKELY(page->compact_string_base == 0)) if (PUGI__UNLIKELY(page->compact_string_base == 0))
page->compact_string_base = value; page->compact_string_base = value;
uint16_t* base = reinterpret_cast<uint16_t*>(reinterpret_cast<char*>(this) - base_offset);
ptrdiff_t offset = value - page->compact_string_base; ptrdiff_t offset = value - page->compact_string_base;
if (PUGI__UNLIKELY(static_cast<uintptr_t>(offset) >= 16777213)) if (*base == 0)
*base = static_cast<uint16_t>(offset >> 7) + 1;
ptrdiff_t remainder = offset - ((*base - 1) << 7);
if (PUGI__UNLIKELY(static_cast<uintptr_t>(remainder) >= 254 || *base == 0))
{ {
compact_set_value<header_offset>(this, value); compact_set_value<header_offset>(this, value);
offset = 16777214; _data = 255;
}
_data0 = static_cast<unsigned char>(offset + 1);
_data1 = static_cast<unsigned char>((offset + 1) >> 8);
_data2 = static_cast<unsigned char>((offset + 1) >> 16);
} }
else else
{ {
_data0 = 0; _data = static_cast<unsigned char>(remainder + 1);
_data1 = 0; }
_data2 = 0; }
else
{
_data = 0;
} }
} }
operator char_t*() const operator char_t*() const
{ {
unsigned int data = _data0 + (_data1 << 8) + (_data2 << 16); if (_data)
{
if (data) if (PUGI__UNLIKELY(_data == 255))
{
return compact_get_value<header_offset, char_t>(this);
}
else
{ {
xml_memory_page* page = compact_get_page(this, header_offset); xml_memory_page* page = compact_get_page(this, header_offset);
if (data < 16777215) const uint16_t* base = reinterpret_cast<const uint16_t*>(reinterpret_cast<const char*>(this) - base_offset);
return page->compact_string_base + (data - 1); assert(*base);
else
return compact_get_value<header_offset, char_t>(this); ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1);
return page->compact_string_base + offset;
}
} }
else else
return 0; return 0;
} }
private: private:
unsigned char _data0; unsigned char _data;
unsigned char _data1;
unsigned char _data2;
}; };
PUGI__NS_END PUGI__NS_END
#endif #endif
@ -965,17 +974,19 @@ namespace pugi
{ {
struct xml_attribute_struct struct xml_attribute_struct
{ {
xml_attribute_struct(impl::xml_memory_page* page): header(page, 0) xml_attribute_struct(impl::xml_memory_page* page): header(page, 0), namevalue_base(0)
{ {
PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 12); PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 12);
} }
impl::compact_header header; impl::compact_header header;
unsigned char padding; unsigned char padding[3];
impl::compact_string_fat<4> name; uint16_t namevalue_base;
impl::compact_string_fat<7> value;
impl::compact_string<8, 2> name;
impl::compact_string<9, 3> value;
impl::compact_pointer<xml_attribute_struct, 10> prev_attribute_c; impl::compact_pointer<xml_attribute_struct, 10> prev_attribute_c;
impl::compact_pointer<xml_attribute_struct, 11, 0> next_attribute; impl::compact_pointer<xml_attribute_struct, 11, 0> next_attribute;
@ -983,17 +994,19 @@ namespace pugi
struct xml_node_struct struct xml_node_struct
{ {
xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type - 1) xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type - 1), namevalue_base(0)
{ {
PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 16); PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 16);
} }
impl::compact_header header; impl::compact_header header;
unsigned char padding; unsigned char padding[3];
impl::compact_string_fat<4> name; uint16_t namevalue_base;
impl::compact_string_fat<7> value;
impl::compact_string<8, 2> name;
impl::compact_string<9, 3> value;
impl::compact_pointer_parent<xml_node_struct, 10> parent; impl::compact_pointer_parent<xml_node_struct, 10> parent;