More Related Content Similar to Ch4 pugixml (8) More from Kyungryul KIM (20) Ch4 pugixml2. XML ํ์ฑ ๋ชจํ.
โ SAX(Simple API for XML) - ์คํธ๋ฆผ๊ณผ โํ๊ทธ ์์, ๋, ๋ฌธ
์์๋ฃโ๋ฑ์ ์ฝ๋ฐฑ์ผ๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ.!
โ Pull Parsing - SAX ์ ์ฌ, iterator ๊ฐ์ฒด๋ฅผ ํตํด ์ ์ด.!
โ DOM(Document Object Model) - ์
๋ ฅ์ ๋ฌธ์ ๊ฐ์ฒด๋ก ๋ณ
ํํ ์ฒ๋ฆฌ.
3. pugixml DOM ํ์
โ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ค์ด๊ฐ ์ ๋๋ก ์์ ๋ฌธ์.!
โ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ค์ด ์๋ก ์ฐธ์กฐํ๋ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ๋ฌธ์!
โ ๋ณต์กํ ๋ฐฉ์์ผ๋ก ๋ณํํด์ผ ํ๋ ๋ฌธ์.
4. pugixml ์ค๊ณ์์ ์ ํ
โ ์์ฃผ ๋น ๋ฅด๊ณ ๊ฐ๋ฒผ์ด DOM ๊ธฐ๋ฐ XML ์กฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ
๋ชฉํ๋ก ๊ฐ๋ฐ.!
โ ์ฑ๋ฅ๊ณผ XML ๊ฒ์ฆ์ ์ ์ถฉ์ .!
โ well-formed ๊ฒ์ฆ.!
โ DTD(Document Type Declaration)์ ๊ฒ์ฆ ์ํจ.!
โ ์ข
์ข
well-formed ๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์ฑ๊ณต์ผ๋ก ์ฒ๋ฆฌ.
5. ํ์ฑ
โ ํ ํฐ ์คํธ๋ฆผ ๋์ ๋ฌธ์ ์คํธ๋ฆผ์ ๋ํด ํ์ฑ์ ์ํ.!
โ UTF-8 ๋ฌธ์๋ง ์ง์.!
โ ์ ์๋ฆฌ ํ์ฑ(In-place parsing) - ์คํธ๋ฆผ์ ์๋ ์๋ฃ๋ฅผ ์ง
์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์.โจ
๋ฌธ์์ด ๋ณต์ฌ๋ฅผ ์ต์ํํ๊ธฐ ์ํด.
6. In-place parsing
โ ๋ฌธ์์ด์ ๋ง๋๋ฉด ๊ทธ ๋ฌธ์์ด์ ํฌ์ธํฐ์ ๊ธธ์ด๋ฅผ ์ ์ฅ.!
โ ์ฑ๋ฅ ์ข์์ง์ง๋ง, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ฆ๊ฐ.โจ
- ์๋ณธ ์คํธ๋ฆผ ์ ์ง.
< n > T h e n o d e t e x t < / n >
ํฌ์ธํฐ0xabc3, ๊ธธ์ด 130xabc0
7. In-place parsing - ๋๋ฌธ์ ์ฒ๋ฆฌ
โ ๋ฌธ์์ด ์ ๊ทผ์ ๋ณด๋ค ๋น ๋ฅด๊ฒ ํ๊ธฐ ์ํ์ฌ ๋๋ฌธ์๋ฅผ ์ฝ์
.!
โ XML์ ๋ฌธ์์ด ๋ ๋ค์ ๋ฌธ์๋ < ๊ธฐํธ๋ก ๊ตฌ๋ถ๋จ.
< n > T h e n o d e t e x t 0 / n >
ํฌ์ธํฐ0xabc3, ๊ธธ์ด 130xabc0
8. In-place parsing - ๋ฌธ์ ํํ ์ฒ๋ฆฌ
โ ๋ฌธ์์ด์ด ํํ๊ณผ ๋ค๋ฅธ ๊ฒฝ์ฐ ํ์ฑ์ค ์ฒ๋ฆฌ.!
โ `line1xDxAline2xDline3xAxA` ์โจ
line1xAline2xAline3xAxA` ๋ก ๋ณํ.!
โ ๋ฌธ์ ์ฐธ์กฐ ํ์ฅ - a ์ a ๋ก ๋ณํ.!
โ ๊ฐ์ฒด ์ฐธ์กฐ ํ์ฅ - < (<), >(>), "(โ), '(โ);
&(&)!
โ ํน์ฑ ๊ฐ ์ ๊ทํ(Attribute-value normalization) - ๋ชจ๋ ๊ณต
๋ฐฑ๋ฌธ์๋ฅผ ๋น์นธ์ผ๋ก ๋ณํ.
9. In-place parsing - ๋ฌธ์ ํํ ์ฒ๋ฆฌ
โ ๋ณํ ๋๋ฌธ์ ๋ฌผ์์ด์ด ๋ ๊ธธ์ด์ ธ์๋ ์๋๋ค.!
โ ๋ณํ ๊ฒฐ๊ณผ๊ฐ ๋ ๊ธธ๋ฉด ๋ฌธ์ ์๋ฃ๋ฅผ ๋ฎ์ด ์ธ ์ ์๊ธฐ ๋๋ฌธ.
< n > A & # 3 2 ; & l t ; B . < / n >0xabc0
< n > A < B . 0 l t ; B . < / n >0xabc0
10. In-place parsing - Copy-on-Write
โ memory-mapped ๏ฌle I/O ์ ์ฌ์ฉ.!
โ ๋์ข
๋ฃ์ ํ
์คํธ ๋ณํ์ ์ง์ํ๊ธฐ ์ํด Copy-on-Write ๋ฐฉ์์ ์
์ฉํ์ฌ ์๋ณธ ํ์ผ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ์ ๋ง์.!
โ ํ๋ก์ธ์ค ์ฃผ์ ๊ณต๊ฐ์ ์ง์ ๋์ ์ํค๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ๋ฅผ ํผํ
์ ์์.!
โ ํ์ผ์ด ์บ์๋์ง ์์ ๊ฒฝ์ฐ ์ปค๋์ด ๋ก๋ฉํ๋ฏ๋ก ์
์ถ๋ ฅ๊ณผ ํ์ฑ์ด
๋ณ๋ ฌ์ ์ผ๋ก ์งํ.!
โ ์์ ๋ ํ์ด์ง๋ง ๋ฌผ๋ฆฌ์ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ค
์ผ ์ ์์.
11. ๋ฌธ์๋ณ ์ฐ์ฐ์ ์ต์ ํโจ
Optimizing character-wise operations
โ ๋ฌธ์ ํ๋์ ์๋น๋ ํ๊ท ํ๋ก์ธ์ ์ฃผ๊ธฐ(cycle) ์์ด๋ค.!
โ ๋ฌธ์ ์งํฉ ์์ ์ฌ๋ถ ๊ฒ์ถโจ
ํ ๋ฌธ์๊ฐ ์ด๋ค ๋ฌธ์ ์งํฉ์ ์ํ๋์ง ํ์ ํ๋ ๊ฒ.
12. ! enum chartype_t!
! {!
! ! ct_parse_pcdata = 1,! // 0, &, r, <!
! ! ct_parse_attr = 2,!! // 0, &, r, ', "!
! ! ct_parse_attr_ws = 4,! // 0, &, r, ', ", n, tab!
! ! ct_space = 8,! ! ! // r, n, space, tab!
! ! ct_parse_cdata = 16,! // 0, ], >, r!
! ! ct_parse_comment = 32,!// 0, -, >, r!
! ! ct_symbol = 64,! ! ! // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, .!
! ! ct_start_symbol = 128! // Any symbol > 127, a-z, A-Z, _, :!
! };!
!
! static const unsigned char chartype_table[256] =!
! {!
! ! 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15!
! ! 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31!
! ! 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47!
! ! 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63!
! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95!
! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127!
!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+!
! ! โฆ โฆ โฆ!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192!
! };!
!
! bool ischartype_utf8(char c, chartype_t ct){!
! ! return ct & chartype_table[(unsigned char)c];!
! }!
13. ํน์ ๊ตฌ๊ฐ์ ๋ชจ๋ ๋ฌธ์
โ ์ฃผ์ด์ง ๋ฌธ์๊ฐ ์ซ์์ธ์ง ํ์ ํ๋ ํจ์!
โ bool isdigit(char ch) { return (ch >= '0' && ch <= '9'); }!
โ bool isdigit(char ch) { return (unsigned)(ch - '0') < 10; }
14. UTF-8 ๋ฐ์ดํธ์ด
โ ์ฐ์๋ 4 ๋ฐ์ดํธ๊ฐ ASCII ๊ธฐํธ๋ฅผ ๋ํ๋ด๋ UTF-8 ๋ฐ์ดํธ
์ด์ธ์ง ํ๋ณํ๋ ์ฝ๋.!
โ (*(const uint32_t*)data & 0x80808080) == 0
15. ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ is*() ํจ์
โ ์ฑ๋ฅ์ด ์ค์ํ ์ฝ๋์์๋ isalpha()๋ฑ์ ํผํด์ผ ํจ.!
โ locale ์ด โCโ ์ธ์ง ์ ๊ฒํ๋ ๊ณผ์ ๋๋ฌธ.
17. PCDATA ํ์ฑ ํจ์
โ bool ํ๋๊ทธ 2๊ฐ -> 4๊ฐ ๋ณํ.!
โ ๋ฌธ์๋ค์ ๋ฌธ์ ์งํฉ ํ์ ์ด
์ฉ.
template <bool opt_eol, bool opt_escape> struct!
! strconv_pcdata_impl {!
! static char_t* parse(char_t* s) {!
! gap g;!
! while (true) {!
! while (!PUGI__IS_CHARTYPE(*s, ct_parse_pcdata)) ++s;!
! if (*s == '<') { // PCDATA ends here!
! *g.flush(s) = 0;!
! return s + 1;!
! } else if (opt_eol && *s == 'r') { // 0x0d or 0x0d 0x0a pair!
! *s++ = 'n'; // replace first one with 0x0a!
! if (*s == 'n') g.push(s, 1);!
! } else if (opt_escape && *s == '&') {!
! s = strconv_escape(/s, g);!
! } else if (*s == 0) {!
! return s;!
! } else {!
! ++s;!
! }!
! }!
! }!
! };!
18. PCDATA ํ(GAP) ๊ด๋ฆฌ
โ " ๋ฅผ โ ๋ก ๋์ฒดํ๋ฉด ๋ฌธ์ ๋ค์ฏ๊ฐ์ ํ์ด ์๊น.!
โ ๋ ํ์ ๋ณํฉ - ๊ธฐ์กด ํ๊ณผ ์ ํ ์ฌ์ด ์๋ฃ๋ฅผ ์์ผ๋ก ์ฎ๊น.!
โ ์ฝ๊ธฐ/์ฐ๊ธฐ ํฌ์ธํฐ๋ณด๋ค ์ข ๋ ๋น ๋ฅด๊ฒ ๋ณํฉ(memmove)
19. ์ ์ด ํ๋ฆ์ ์ต์ ํ
Optimizing control flow
โ ์ฌ๊ท์ ํ๊ฐ ํ์(recursive-descent parser) ํํ์์ ์ฑ
๋ฅ ํฅ์์ ์ํด ์ฌ๊ท๋ฅผ ๋ฐ๋ณต ๋ฃจํ๋ก ๋ณ๊ฒฝ.!
โ ๋
ธ๋ ์ปค์๋ ์คํ๋ฐฉ์์ผ๋ก ๋์.!
โ ์คํ ๊ณต๊ฐ ์๋น๋์ด ์
๋ ฅ ๋ฌธ์์ ๋ฌด๊ดํ๊ฒ ์ผ์ .!
โ ์์ ์ฑ์ ์ฆ๊ฐ.!
โ ์ ์ฌ์ ์ธ ๋น์ผ ํจ์ ํธ์ถ์ ํผํจ. ???
20. ๋ถ๊ธฐ ์์์ ์ฝ๋ ๊ตญ์์ฑ
โ ์์ฃผ ์คํ๋๋ ๋ถ๋ถ(ํ๊ทธ์ด๋ฆ,์์ฑ)๊ณผ ๊ฑฐ์ ์คํ๋์ง ์
๋ ๋ถ๋ถ(DOCTYPE)!
โ ์ฒ๋ฆฌ ํ๋ฅ - โ<โ ๋ฌธ์ ๋ค์ โํ๊ทธ ์ด๋ฆโ, โ/โ, โ!โ, โ?โ ์์ ํ๋ฅ
๋ก ๋ํ๋จ.!
โ ์ฝ๋ ์กฐ๊ฐ๋ค์ ํ๋ฅ ์ ๋ฐ๋ผ ์ฌ๋ฐฐ์น!
โ ์ธ๋ผ์ธ ์ฝ๋๋์ ์ ํ.
21. โ ์กฐ๊ฑด ๋ถ๊ธฐ๋ค์ ํ๋ฅ ์ด ๋์ ๊ฑฐ์์ ๋ฎ์ ๊ฒ ์์๋ก ์ฌ๋ฐฐ์น.!
โ ํ๊ท ์ ์ธ ์กฐ๊ฑด ํ์ ๋ฐ ๋ถ๊ธฐ ์ํ ํ์๊ฐ ์ต์ํ.
! if (data[0] == '<')!
! {!
! if (data[1] == '!') { ... }!
! else if (data[1] == '/') { ... }!
! else if (data[1] == '?') { ... }!
! else { /* start-tag or unrecognized tag */ }!
! }!
!
! if (data[0] == '<')!
! {!
! if (PUGI__IS_CHARTYPE(data[1], ct_start_symbol)) { /* start-tag */ }!
! else if (data[1] == '/') { ... }!
! else if (data[1] == '!') { ... }!
! else if (data[1] == '?') { ... }!
! else { /* unrecognized tag */ }!
! }!
22. ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ ๋ณด์ฅ
โ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ง๊ธฐ ์ํด.!
โ ํ์ฌ ์ฝ๊ธฐ์ ๋ฒํผ ๋์ ๋น๊ต.!
โ ํ๋์ ๋ ์ง์คํฐ๊ฐ ๋ ํ์.!
โ ํจ์ ํธ์ถ์ ํ์ฌ ์์น์ ๋์์น๋ฅผ ์ ๋ฌํ ํฌ์ธํฐ ํ์!
โ ๋๋ฌธ์ ์ฒ๋ฆฌ.!
โ ์
๋ ฅ ๋ฒํผ์ ๋ฒํผ ํฌ๊ธฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒฝ์ฐ ์ฌ์ฉ์ ๋ถํธํจ
๋ฐ์.
23. DOM ์๋ฃ ๊ตฌ์กฐ
โ ์ฐ๊ฒฐ ๋ชฉ๋ก ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ
๋ ๋
ธ๋ ์์ ์ O(1).!
โ ์ฐ๊ฒฐ ๋ชฉ๋ก ์ ๊ทผ ๋ฐฉ์- ๊ณ ์ ํฌ๊ธฐ ํ
๋น์ ์ํ ๋น ๋ฅธ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์๋ฅผ ์ค
๊ณํ๋ ๊ฒ์ด ์์ ํฌ๊ธฐ ํ ๋น์๋ณด๋ค
์ฝ๋ค.!
โ ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ - last_child ์ ๊ฑฐ,
prev_sibling_cyclic ์ผ๋ก ๋์ฒดO(1).
struct Node {!
Node* first_child;!
Node* last_child;!
Node* prev_sibling;!
Node* next_sibling;!
};!
struct Node {!
Node* first_child;!
Node* prev_sibling_cyclic;!
Node* next_sibling;!
};!
24. Node* last_child(Node* node) {!
return (node->first_child) ?!
node->first_child->prev_sibling_cyclic : NULL;!
}!
!
Node* prev_sibling(Node* node) {!
return (/node->prev_sibling_cyclic->next_sibling) ?!
node->prev_sibling_cyclic : NULL;!
}!
25. ์คํ ๊ธฐ๋ฐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น
โ ๊ฐ๋ณ ํฌ๊ธฐ ๋ฌธ์์ด ํ ๋น.!
โ ํ ๋น ๊ตญ์์ฑ์ ์ ์ง.!
โ DOM ํ๊ดด ์๋์ ์ํ ๋ฉ๋ชจ๋ฆฌ ํด์ .
26. ์คํ ํ ๋น์
const size_t allocator_page_size = 32768;!
struct allocator_page {!
allocator_page* next_page;!
size_t offset;!
char data[allocator_page_size];!
};!
struct allocator_state {!
allocator_page* current;!
};!
!
void* allocate_new_page_data(size_t size) {!
size_t extra_size = (size >
allocator_page_size) ?!
size - allocator_page_size : 0;!
return malloc(sizeof(allocator_page) +
extra_size);!
}
void* allocate_oob(allocator_state* state,
size_t size) {!
allocator_page* page =
(allocator_page*)allocate_new_page_data(siz
e);!
// add page to page list!
page->next_page = state->current;!
state->current = page;!
// user data is located at the beginning
of the page!
page->offset = size;!
return page->data;!
}!
!
void* allocate(allocator_state* state,
size_t size) {!
if (state->current->offset + size <=
allocator_page_size) {!
void* result = state->current->data +
state->current->offset;!
state->current->offset += size;!
return result;!
}!
return allocate_oob(state, size);!
}!
27. ์คํ ๊ธฐ๋ฐ ํ ๋น์์ ๋ฉ๋ชจ๋ฆฌ ํด์ ์ง์
โ ๋ฉ๋ชจ๋ฆฌ ํด์ ์ ์ฌ์ฌ์ฉ์ ์ํด ์ฐธ์กฐ ์นด์ดํธ ๋ฐฉ์ ๋์
.!
โ ๋ชจ๋ ํ์ด์ง๋ 32๋ฐ์ดํธ ๊ฒฝ๊ณ๋ก ์ ๋ ฌ๋๊ณ ๋ชจ๋ ํ์ด์ง ํฌ์ธํฐ์
ํ์ ๋ค์ฏ ๋นํธ๋ ํญ์ 0์ด๋ค. ???!
โ 5๋นํธ์ XML ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ.!
โ ํ ๋น๋ ์์์ ์์น๋ฅผ ํ์ด์ง ์์ ์์น๋ฅผ ๊ธฐ์ค์ผ๋ก ์คํ์
์ผ๋ก
์ ์ฅ.!
โ ํ์ด์ง ํฌ์ธํฐ์ ์ฃผ์ => โจ
(allocator_page*)((char*)(object) -object->offset -
offsetof(allocator_page, data))