File: pythonoutputstream.h

package info (click to toggle)
regina-normal 7.4.1-1.1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 154,244 kB
  • sloc: cpp: 295,026; xml: 9,992; sh: 1,344; python: 1,225; perl: 616; ansic: 138; makefile: 26
file content (132 lines) | stat: -rw-r--r-- 5,509 bytes parent folder | download
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

/**************************************************************************
 *                                                                        *
 *  Regina - A Normal Surface Theory Calculator                           *
 *  Python Interface                                                      *
 *                                                                        *
 *  Copyright (c) 1999-2025, Ben Burton                                   *
 *  For further details contact Ben Burton (bab@debian.org).              *
 *                                                                        *
 *  This program is free software; you can redistribute it and/or         *
 *  modify it under the terms of the GNU General Public License as        *
 *  published by the Free Software Foundation; either version 2 of the    *
 *  License, or (at your option) any later version.                       *
 *                                                                        *
 *  As an exception, when this program is distributed through (i) the     *
 *  App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or     *
 *  (iii) Google Play by Google Inc., then that store may impose any      *
 *  digital rights management, device limits and/or redistribution        *
 *  restrictions that are required by its terms of service.               *
 *                                                                        *
 *  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     *
 *  General Public License for more details.                              *
 *                                                                        *
 *  You should have received a copy of the GNU General Public License     *
 *  along with this program. If not, see <https://www.gnu.org/licenses/>. *
 *                                                                        *
 **************************************************************************/

/*! \file pythonoutputstream.h
 *  \brief Supports customised output streams for use with embedded
 *  python interpreters.
 *
 *  The accompanying source file (pythonoutputstream.cpp) should be built
 *  directly into each user interface that requires it.
 *  It is _not_ built into Regina's python module.
 */

#ifndef __PYTHONOUTPUTSTREAM_H
#define __PYTHONOUTPUTSTREAM_H

#include <string>

namespace regina {
    class Packet;
}

namespace regina::python {

/**
 * A custom output stream that can be used by python as sys.stdout or
 * sys.stderr.
 *
 * Data is fed to the output stream by calling write().  This data is
 * buffered - each time a newline is sent or flush() is called, any
 * unprocessed data will be sent to the virtual routine processOutput().
 *
 * Typically a user interface will create a subclass of PythonOutputStream
 * that writes output to an appropriate location (e.g., a python window,
 * or a logger), and call install() to redirect Python's standard output
 * and/or standard error to some object of this subclass.
 */
class PythonOutputStream {
    private:
        std::string buffer;
            /**< The output data that has yet to be processed. */

    public:
        /**
         * Virtual destructor.
         */
        inline virtual ~PythonOutputStream() = default;

        /**
         * Writes data to this output stream.  Note that this data will
         * not be processed until a newline is written or flush() is called.
         *
         * This routine may be called with or without the Python global
         * interpreter lock being held.
         */
        void write(const std::string& data);

        /**
         * Forces any data that has not yet been processed to be
         * sent to processOutput().
         *
         * This routine may be called with or without the Python global
         * interpreter lock being held.
         */
        void flush();

        /**
         * Uses this object for either standard output or standard error.
         *
         * This will set `sys.<streamname>` to this object.
         *
         * \pre \a streamName must be either "stdout" or "stderr".
         * \pre The python bindings for PythonOutputStream have already been
         * set up by calling the static routine addBindings().
         * \pre The Python global interpreter lock is currently held.
         *
         * May throw a std::runtime_error if an error occurs.
         */
        void install(const char* streamName);

        /**
         * Adds python bindings for the base class PythonOutputStream.
         *
         * The class name PythonOutputStream is not added to the main
         * namespace, so the only simple way to access the Python
         * wrapper class is by having an object of that type (such as
         * a redirected sys.stdout or sys.stderr).
         *
         * May throw a std::runtime_error if an error occurs.
         */
        static void addBindings();

    protected:
        /**
         * Process a chunk of data that was sent to this output stream.
         * This routine might for instance display the data to the user
         * or write it to a log file.
         *
         * \pre The Python global interpreter lock is _not_ held.
         */
        virtual void processOutput(const std::string& data) = 0;
};

} // namespace regina::python

#endif