From e4c539a869eb4045711f2b7c2390b0f450be71a1 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Fri, 1 May 2015 22:47:53 -0700 Subject: Implement compact_string with shared storage --- src/pugixml.cpp | 77 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 32 deletions(-) (limited to 'src/pugixml.cpp') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index f8762bf..70dd037 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -892,14 +892,14 @@ PUGI__NS_BEGIN uint16_t _data; }; - template class compact_string_fat + template class compact_string { 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; } @@ -913,50 +913,59 @@ PUGI__NS_BEGIN if (PUGI__UNLIKELY(page->compact_string_base == 0)) page->compact_string_base = value; + uint16_t* base = reinterpret_cast(reinterpret_cast(this) - base_offset); + ptrdiff_t offset = value - page->compact_string_base; - if (PUGI__UNLIKELY(static_cast(offset) >= 16777213)) + if (*base == 0) + *base = static_cast(offset >> 7) + 1; + + ptrdiff_t remainder = offset - ((*base - 1) << 7); + + if (PUGI__UNLIKELY(static_cast(remainder) >= 254 || *base == 0)) { compact_set_value(this, value); - offset = 16777214; + _data = 255; + } + else + { + _data = static_cast(remainder + 1); } - - _data0 = static_cast(offset + 1); - _data1 = static_cast((offset + 1) >> 8); - _data2 = static_cast((offset + 1) >> 16); } else { - _data0 = 0; - _data1 = 0; - _data2 = 0; + _data = 0; } } operator char_t*() const { - unsigned int data = _data0 + (_data1 << 8) + (_data2 << 16); - - if (data) + if (_data) { - xml_memory_page* page = compact_get_page(this, header_offset); - - if (data < 16777215) - return page->compact_string_base + (data - 1); - else + if (PUGI__UNLIKELY(_data == 255)) + { return compact_get_value(this); + } + else + { + xml_memory_page* page = compact_get_page(this, header_offset); + + const uint16_t* base = reinterpret_cast(reinterpret_cast(this) - base_offset); + assert(*base); + + ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1); + + return page->compact_string_base + offset; + } } else return 0; } private: - unsigned char _data0; - unsigned char _data1; - unsigned char _data2; + unsigned char _data; }; - PUGI__NS_END #endif @@ -965,17 +974,19 @@ namespace pugi { 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); } impl::compact_header header; - unsigned char padding; + unsigned char padding[3]; + + uint16_t namevalue_base; - impl::compact_string_fat<4> name; - impl::compact_string_fat<7> value; + impl::compact_string<8, 2> name; + impl::compact_string<9, 3> value; impl::compact_pointer prev_attribute_c; impl::compact_pointer next_attribute; @@ -983,17 +994,19 @@ namespace pugi 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); } impl::compact_header header; - unsigned char padding; + unsigned char padding[3]; + + uint16_t namevalue_base; - impl::compact_string_fat<4> name; - impl::compact_string_fat<7> value; + impl::compact_string<8, 2> name; + impl::compact_string<9, 3> value; impl::compact_pointer_parent parent; -- cgit v1.2.3