| import os.path | |
| from c_common import fsutil | |
| import c_common.tables as _tables | |
| import c_parser.info as _info | |
| BASE_COLUMNS = [ | |
| 'filename', | |
| 'funcname', | |
| 'name', | |
| 'kind', | |
| ] | |
| END_COLUMNS = { | |
| 'parsed': 'data', | |
| 'decls': 'declaration', | |
| } | |
| def _get_columns(group, extra=None): | |
| return BASE_COLUMNS + list(extra or ()) + [END_COLUMNS[group]] | |
| #return [ | |
| # *BASE_COLUMNS, | |
| # *extra or (), | |
| # END_COLUMNS[group], | |
| #] | |
| ############################# | |
| # high-level | |
| def read_parsed(infile): | |
| # XXX Support other formats than TSV? | |
| columns = _get_columns('parsed') | |
| for row in _tables.read_table(infile, columns, sep='\t', fix='-'): | |
| yield _info.ParsedItem.from_row(row, columns) | |
| def write_parsed(items, outfile): | |
| # XXX Support other formats than TSV? | |
| columns = _get_columns('parsed') | |
| rows = (item.as_row(columns) for item in items) | |
| _tables.write_table(outfile, columns, rows, sep='\t', fix='-') | |
| def read_decls(infile, fmt=None): | |
| if fmt is None: | |
| fmt = _get_format(infile) | |
| read_all, _ = _get_format_handlers('decls', fmt) | |
| for decl, _ in read_all(infile): | |
| yield decl | |
| def write_decls(decls, outfile, fmt=None, *, backup=False): | |
| if fmt is None: | |
| fmt = _get_format(infile) | |
| _, write_all = _get_format_handlers('decls', fmt) | |
| write_all(decls, outfile, backup=backup) | |
| ############################# | |
| # formats | |
| def _get_format(file, default='tsv'): | |
| if isinstance(file, str): | |
| filename = file | |
| else: | |
| filename = getattr(file, 'name', '') | |
| _, ext = os.path.splitext(filename) | |
| return ext[1:] if ext else default | |
| def _get_format_handlers(group, fmt): | |
| # XXX Use a registry. | |
| if group != 'decls': | |
| raise NotImplementedError(group) | |
| if fmt == 'tsv': | |
| return (_iter_decls_tsv, _write_decls_tsv) | |
| else: | |
| raise NotImplementedError(fmt) | |
| # tsv | |
| def iter_decls_tsv(infile, extracolumns=None, relroot=fsutil.USE_CWD): | |
| if relroot and relroot is not fsutil.USE_CWD: | |
| relroot = os.path.abspath(relroot) | |
| for info, extra in _iter_decls_tsv(infile, extracolumns): | |
| decl = _info.Declaration.from_row(info) | |
| decl = decl.fix_filename(relroot, formatted=False, fixroot=False) | |
| yield decl, extra | |
| def write_decls_tsv(decls, outfile, extracolumns=None, *, | |
| relroot=fsutil.USE_CWD, | |
| **kwargs | |
| ): | |
| if relroot and relroot is not fsutil.USE_CWD: | |
| relroot = os.path.abspath(relroot) | |
| decls = (d.fix_filename(relroot, fixroot=False) for d in decls) | |
| # XXX Move the row rendering here. | |
| _write_decls_tsv(decls, outfile, extracolumns, kwargs) | |
| def _iter_decls_tsv(infile, extracolumns=None): | |
| columns = _get_columns('decls', extracolumns) | |
| for row in _tables.read_table(infile, columns, sep='\t'): | |
| if extracolumns: | |
| declinfo = row[:4] + row[-1:] | |
| extra = row[4:-1] | |
| else: | |
| declinfo = row | |
| extra = None | |
| # XXX Use something like tables.fix_row() here. | |
| declinfo = [None if v == '-' else v | |
| for v in declinfo] | |
| yield declinfo, extra | |
| def _write_decls_tsv(decls, outfile, extracolumns, kwargs): | |
| columns = _get_columns('decls', extracolumns) | |
| if extracolumns: | |
| def render_decl(decl): | |
| if type(row) is tuple: | |
| decl, *extra = decl | |
| else: | |
| extra = () | |
| extra += ('???',) * (len(extraColumns) - len(extra)) | |
| *row, declaration = _render_known_row(decl) | |
| row += extra + (declaration,) | |
| return row | |
| else: | |
| render_decl = _render_known_decl | |
| _tables.write_table( | |
| outfile, | |
| header='\t'.join(columns), | |
| rows=(render_decl(d) for d in decls), | |
| sep='\t', | |
| **kwargs | |
| ) | |
| def _render_known_decl(decl, *, | |
| # These match BASE_COLUMNS + END_COLUMNS[group]. | |
| _columns = 'filename parent name kind data'.split(), | |
| ): | |
| if not isinstance(decl, _info.Declaration): | |
| # e.g. Analyzed | |
| decl = decl.decl | |
| rowdata = decl.render_rowdata(_columns) | |
| return [rowdata[c] or '-' for c in _columns] | |
| # XXX | |
| #return _tables.fix_row(rowdata[c] for c in columns) |