File size: 4,729 Bytes
d94b56e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# -*- coding: utf-8 -*-
#
# pyhwp : hwp file format parser in python
# Copyright (C) 2010-2023 mete0r <https://github.com/mete0r>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
class STARTEVENT:
pass
class ENDEVENT:
pass
def prefix_event(level_prefixed_items, root_item=None):
''' convert iterable of (level, item) into iterable of (event, item)
'''
baselevel = None
stack = [root_item]
for level, item in level_prefixed_items:
if baselevel is None:
baselevel = level
level = 0
else:
level -= baselevel
while level + 1 < len(stack):
yield ENDEVENT, stack.pop()
while len(stack) < level + 1:
raise Exception('invalid level: %d, %d, %s' %
(level, len(stack) - 1, item))
assert(len(stack) == level + 1)
stack.append(item)
yield STARTEVENT, item
while 1 < len(stack):
yield ENDEVENT, stack.pop()
def prefix_ancestors(event_prefixed_items, root_item=None):
''' convert iterable of (event, item) into iterable of (ancestors, item)
'''
stack = [root_item]
for event, item in event_prefixed_items:
if event is STARTEVENT:
yield stack, item
stack.append(item)
elif event is ENDEVENT:
stack.pop()
def prefix_ancestors_from_level(level_prefixed_items, root_item=None):
''' convert iterable of (level, item) into iterable of (ancestors, item)
@param level_prefixed items: iterable of tuple(level, item)
@return iterable of tuple(ancestors, item)
'''
baselevel = None
stack = [root_item]
for level, item in level_prefixed_items:
if baselevel is None:
baselevel = level
level = 0
else:
level -= baselevel
while level + 1 < len(stack):
stack.pop()
while len(stack) < level + 1:
raise Exception('invalid level: %d, %d, %s' %
(level, len(stack) - 1, item))
assert(len(stack) == level + 1)
yield stack, item
stack.append(item)
def build_subtree(event_prefixed_items):
''' build a tree from (event, item) stream
Example Scenario::
...
(STARTEVENT, rootitem) # should be consumed by the caller
--- call build_subtree() ---
(STARTEVENT, child1) # consumed by build_subtree()
(STARTEVENT, grandchild) # (same)
(ENDEVENT, grandchild) # (same)
(ENDEVENT, child1) # (same)
(STARTEVENT, child2) # (same)
(ENDEVENT, child2) # (same)
(ENDEVENT, rootitem) # same, buildsubtree() returns
--- build_subtree() returns ---
(STARTEVENT, another_root)
...
result will be (rootitem, [(child1, [(grandchild, [])]),
(child2, [])])
'''
childs = []
for event, item in event_prefixed_items:
if event == STARTEVENT:
childs.append(build_subtree(event_prefixed_items))
elif event == ENDEVENT:
return item, childs
def iter_subevents(event_prefixed_items):
level = 0
for event, item in event_prefixed_items:
yield event, item
if event is STARTEVENT:
level += 1
elif event is ENDEVENT:
if level > 0:
level -= 1
else:
return
def tree_events(rootitem, childs):
''' generate tuples of (event, item) from a tree
'''
yield STARTEVENT, rootitem
for k in tree_events_multi(childs):
yield k
yield ENDEVENT, rootitem
def tree_events_multi(trees):
''' generate tuples of (event, item) from trees
'''
for rootitem, childs in trees:
for k in tree_events(rootitem, childs):
yield k
|