/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. * * signal.h - Signal & slot implementation */ #ifndef __LIBCAMERA_SIGNAL_H__ #define __LIBCAMERA_SIGNAL_H__ #include #include #include #include #include #include namespace libcamera { class SignalBase { public: void disconnect(Object *object); protected: using SlotList = std::list; void connect(BoundMethodBase *slot); void disconnect(std::function match); SlotList slots(); private: SlotList slots_; }; template class Signal : public SignalBase { public: ~Signal() { disconnect(); } #ifndef __DOXYGEN__ template::value> * = nullptr> void connect(T *obj, R (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) { Object *object = static_cast(obj); SignalBase::connect(new BoundMethodMember(obj, object, func, type)); } template::value> * = nullptr> #else template #endif void connect(T *obj, R (T::*func)(Args...)) { SignalBase::connect(new BoundMethodMember(obj, nullptr, func)); } template void connect(R (*func)(Args...)) { SignalBase::connect(new BoundMethodStatic(func)); } void disconnect() { SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) { return true; }); } template void disconnect(T *obj) { SignalBase::disconnect([obj](SlotList::iterator &iter) { return (*iter)->match(obj); }); } template void disconnect(T *obj, R (T::*func)(Args...)) { SignalBase::disconnect([obj, func](SlotList::iterator &iter) { BoundMethodArgs *slot = static_cast *>(*iter); if (!slot->match(obj)) return false; /* * If the object matches the slot, the slot is * guaranteed to be a member slot, so we can safely * cast it to BoundMethodMember to match * func. */ return static_cast *>(slot)->match(func); }); } template void disconnect(R (*func)(Args...)) { SignalBase::disconnect([func](SlotList::iterator &iter) { BoundMethodArgs *slot = static_cast *>(*iter); if (!slot->match(nullptr)) return false; return static_cast *>(slot)->match(func); }); } void emit(Args... args) { /* * Make a copy of the slots list as the slot could call the * disconnect operation, invalidating the iterator. */ for (BoundMethodBase *slot : slots()) static_cast *>(slot)->activate(args...); } }; } /* namespace libcamera */ #endif /* __LIBCAMERA_SIGNAL_H__ */ /libcamera.git/tree/utils/tuning/libtuning/generators/yaml_output.py?id=c79fa47aac9b38865dab5e9f29030903bf460c46'>yaml_output.py
blob: 8f22d386f1b3422bd4588b7aad5dc8116fd3b4a3 (plain)
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
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright 2022 Paul Elder <paul.elder@ideasonboard.com>
#
# Generate tuning file in YAML format

from .generator import Generator

from numbers import Number
from pathlib import Path

import libtuning.utils as utils


class YamlOutput(Generator):
    def __init__(self):
        super().__init__()

    def _stringify_number_list(self, listt: list):
        line_wrap = 80

        line = '[ ' + ', '.join([str(x) for x in listt]) + ' ]'
        if len(line) <= line_wrap:
            return [line]

        out_lines = ['[']
        line = ' '
        for x in listt:
            x_str = str(x)
            # If the first number is longer than line_wrap, it'll add an extra line
            if len(line) + len(x_str) > line_wrap:
                out_lines.append(line)
                line = f'  {x_str},'
                continue
            line += f' {x_str},'
        out_lines.append(line)
        out_lines.append(']')

        return out_lines

    # @return Array of lines, and boolean of if all elements were numbers
    def _stringify_list(self, listt: list):
        out_lines = []

        all_numbers = set([isinstance(x, Number) for x in listt]).issubset({True})

        if all_numbers:
            return self._stringify_number_list(listt), True

        for value in listt:
            if isinstance(value, Number):
                out_lines.append(f'- {str(value)}')
            elif isinstance(value, str):
                out_lines.append(f'- "{value}"')
            elif isinstance(value, list):
                lines, all_numbers = self._stringify_list(value)

                if all_numbers:
                    out_lines.append( f'- {lines[0]}')
                    out_lines +=     [f'  {line}' for line in lines[1:]]
                else:
                    out_lines.append( f'-')
                    out_lines += [f'  {line}' for line in lines]
            elif isinstance(value, dict):
                lines = self._stringify_dict(value)
                out_lines.append( f'- {lines[0]}')
                out_lines +=     [f'  {line}' for line in lines[1:]]

        return out_lines, False

    def _stringify_dict(self, dictt: dict):
        out_lines = []

        for key in dictt:
            value = dictt[key]

            if isinstance(value, Number):
                out_lines.append(f'{key}: {str(value)}')
            elif isinstance(value, str):
                out_lines.append(f'{key}: "{value}"')
            elif isinstance(value, list):
                lines, all_numbers = self._stringify_list(value)

                if all_numbers:
                    out_lines.append( f'{key}: {lines[0]}')
                    out_lines +=     [f'{" " * (len(key) + 2)}{line}' for line in lines[1:]]
                else:
                    out_lines.append( f'{key}:')
                    out_lines +=     [f'  {line}' for line in lines]
            elif isinstance(value, dict):
                lines = self._stringify_dict(value)
                out_lines.append( f'{key}:')
                out_lines +=     [f'  {line}' for line in lines]

        return out_lines

    def write(self, output_file: Path, output_dict: dict, output_order: list):
        out_lines = [
            '%YAML 1.1',
            '---',
            'version: 1',
            # No need to condition this, as libtuning already guarantees that
            # we have at least one module. Even if the module has no output,
            # its prescence is meaningful.
            'algorithms:'
        ]

        for module in output_order:
            out_lines.append(f'  - {module.out_name}:')

            if len(output_dict[module]) == 0:
                continue

            if not isinstance(output_dict[module], dict):
                utils.eprint(f'Error: Output of {module.type} is not a dictionary')
                continue

            lines = self._stringify_dict(output_dict[module])
            out_lines += [f'      {line}' for line in lines]

        with open(output_file, 'w', encoding='utf-8') as f:
            for line in out_lines:
                f.write(f'{line}\n')