Add library.scan_hierarchy to quickly gather layout stats
This commit is contained in:
parent
34a334f6f3
commit
fbe5cee7f5
@ -1,16 +1,17 @@
|
||||
"""
|
||||
File-level read/write functionality.
|
||||
"""
|
||||
from typing import List, Dict, Tuple, Optional, BinaryIO, TypeVar, Type
|
||||
from typing import List, Dict, Tuple, Optional, BinaryIO, TypeVar, Type, MutableMapping
|
||||
import io
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass
|
||||
from collections import defaultdict
|
||||
|
||||
from .basic import KlamathError
|
||||
from .record import Record
|
||||
|
||||
from .records import HEADER, BGNLIB, ENDLIB, UNITS, LIBNAME
|
||||
from .records import BGNSTR, STRNAME, ENDSTR
|
||||
from .records import BGNSTR, STRNAME, ENDSTR, SNAME, COLROW, ENDEL
|
||||
from .records import BOX, BOUNDARY, NODE, PATH, TEXT, SREF, AREF
|
||||
from .elements import Element, Reference, Text, Box, Boundary, Path, Node
|
||||
|
||||
@ -183,3 +184,50 @@ def read_elements(stream: BinaryIO) -> List[Element]:
|
||||
stream.seek(size, io.SEEK_CUR)
|
||||
size, tag = Record.read_header(stream)
|
||||
return data
|
||||
|
||||
|
||||
def scan_hierarchy(stream: BinaryIO) -> Dict[bytes, Dict[bytes, int]]:
|
||||
"""
|
||||
Scan through a GDS file, building a table of instance counts
|
||||
`{b'structure_name': {b'ref_name': count}}`.
|
||||
|
||||
This is intended to provide a fast overview of the file's
|
||||
contents without performing a full read of all elements.
|
||||
|
||||
Args:
|
||||
stream: Seekable stream to read from. Should be positioned
|
||||
before the first structure record, but possibly
|
||||
already past the file header.
|
||||
"""
|
||||
structures = {}
|
||||
|
||||
ref_name = None
|
||||
ref_count = None
|
||||
cur_structure: MutableMapping[bytes, int] = defaultdict(int)
|
||||
size, tag = Record.read_header(stream)
|
||||
while tag != ENDLIB.tag:
|
||||
if tag == BGNSTR.tag:
|
||||
stream.seek(size, io.SEEK_CUR)
|
||||
name = STRNAME.read(stream)
|
||||
if name in structures:
|
||||
raise KlamathError(f'Duplicate structure name: {name!r}')
|
||||
cur_structure = defaultdict(int)
|
||||
structures[name] = cur_structure
|
||||
ref_name = None
|
||||
ref_count = None
|
||||
elif tag == SNAME.tag:
|
||||
ref_name = SNAME.read_data(stream, size)
|
||||
elif tag == COLROW.tag:
|
||||
colrow = COLROW.read_data(stream, size)
|
||||
ref_count = colrow[0] * colrow[1]
|
||||
elif tag == ENDEL.tag:
|
||||
if ref_count is None:
|
||||
ref_count = 1
|
||||
assert(ref_name is not None)
|
||||
cur_structure[ref_name] += ref_count
|
||||
else:
|
||||
stream.seek(size, io.SEEK_CUR)
|
||||
size, tag = Record.read_header(stream)
|
||||
|
||||
dict_structures = {key: dict(value) for key, value in structures.items()}
|
||||
return dict_structures
|
||||
|
Loading…
Reference in New Issue
Block a user