Files
pip/libs/main/core/picout.cpp
Бычков Андрей 724a2dffcf picout and clean
2022-08-08 16:44:37 +03:00

725 lines
22 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
PIP - Platform Independent Primitives
Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "picout.h"
#include "pibytearray.h"
#include "pistack.h"
#include "piobject.h"
#include "pistring_std.h"
#ifdef HAS_LOCALE
# include <locale>
# include <codecvt>
#endif
#ifdef WINDOWS
# include <windows.h>
# include <wingdi.h>
# include <wincon.h>
# define COMMON_LVB_UNDERSCORE 0x8000
#endif
//! \~\class PICout picout.h
//! \~\details
//! \~english \section PICout_sec0 Synopsis
//! \~russian \section PICout_sec0 Краткий обзор
//! \~english
//! This class provide many stream operators for output with some features.
//! Output to %PICout is thread-sequential, i.e. doesn`t mixed from parallel
//! threads.
//!
//! \~russian
//! Данный класс предоставляет множество операторов для вывода в консоль.
//! Вывод в %PICout потоково-последовательный, т.е. не смешивается из параллельных
//! потоков.
//!
//! \~english \section PICout_sec1 Features
//! \~russian \section PICout_sec1 Особенности
//! \~english
//! * support text formatting (color, style)
//! * insertion spaces between entries
//! * insertion new line at the end of output
//! * strings are quoted
//! * custom output operator can be easily written
//! * can outpur to console, internal buffer or both
//!
//! \~russian
//! * поддержка форматирования (цвет, стиль)
//! * вставка пробелов между выводами
//! * вставка новой строки после последнего вывода
//! * строки обрамляются кавычками
//! * легко создавать сови операторы вывода
//! * может выводить в консоль, внутренний буфер или в оба места
//!
//! \~english \section PICout_ex0 Usage
//! \~russian \section PICout_ex0 Использование
//! \~\snippet picout.cpp 0
//!
//! \~english \section PICout_ex1 Writing your own output operator
//! \~russian \section PICout_ex1 Создание своего оператора вывода
//! \~\snippet picout.cpp own
//!
//! \addtogroup Core
//! \{
//! \~\class PICout::Notifier picout.h
//! \~\brief
//! \~english Class for emit notifications of PICout
//! \~russian Класс для посылки событий от PICout
//!
//! \~english \section PICoutNotifier_sec0 Synopsis
//! \~russian \section PICoutNotifier_sec0 Краткий обзор
//! \~english
//! This class used as PICout events emitter. When
//! PICout constructs with external PIString* buffer
//! and some ID, last copy of this PICout on delete
//! emit event "finished()" on object Notifier::object().
//! Sample:
//!
//! \~russian
//! Этот класс используется как источник событий PICout.
//! Когда PICout сконструирован с внешним буфером PIString*
//! и каким-то ID, последняя копия этого PICout при уничтожении
//! посылает событие "finished()" у объекта Notifier::object().
//! Пример:
//!
//! \~\snippet picout.cpp notifier
//!
//! \}
class NotifierObject: public PIObject {
PIOBJECT(NotifierObject)
public:
NotifierObject() {}
EVENT2(finished, int, id, PIString*, buffer);
};
PICout::Notifier::Notifier() {
o = new NotifierObject();
}
PICout::Notifier * PICout::Notifier::instance() {
static PICout::Notifier * ret = new PICout::Notifier();
return ret;
}
PIObject * PICout::Notifier::object() {
return instance()->o;
}
using namespace PICoutManipulators;
PIMutex & PICout::__mutex__() {static PIMutex * ret = new PIMutex(); return *ret;}
PIString & PICout::__string__() {static PIString * ret = new PIString(); return *ret;}
PICout::OutputDevices PICout::devs = PICout::StdOut;
PRIVATE_DEFINITION_START(PICout)
PIStack<PICoutControls> cos_;
#ifdef WINDOWS
static void * hOut;
static WORD dattr;
static DWORD smode;
#endif
PRIVATE_DEFINITION_END(PICout)
#ifdef WINDOWS
void * PICout::__Private__::hOut = 0;
WORD PICout::__Private__::dattr = 0;
DWORD PICout::__Private__::smode = 0;
#endif
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
buffer_ = nullptr;
init();
}
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
buffer_ = nullptr;
if (act_) init();
}
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), act_(other.act_), cnb_(other.cnb_), attr_(other.attr_),
id_(other.id_), buffer_(other.buffer_), co_(other.co_) {
}
PICout::~PICout() {
if (!act_) return;
if (fc_) applyFormat(PICoutManipulators::Default);
if (cc_) return;
newLine();
if ((co_ & NoLock) != NoLock) {
PICout::__mutex__().unlock();
}
if (buffer_) {
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
}
}
PICout & PICout::operator <<(PICoutAction v) {
if (!act_) return *this;
#ifdef WINDOWS
CONSOLE_SCREEN_BUFFER_INFO sbi;
COORD coord;
CONSOLE_CURSOR_INFO curinfo;
#endif
switch (v) {
case PICoutManipulators::Flush:
if (!buffer_ && isOutputDeviceActive(StdOut)) {
std::cout << std::flush;
}
break;
case PICoutManipulators::Backspace:
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
coord.X = piMax<int>(0, int(coord.X) - 1);
SetConsoleCursorPosition(__Private__::hOut, coord);
printf(" ");
SetConsoleCursorPosition(__Private__::hOut, coord);
#else
printf("\e[1D \e[1D");
#endif
}
break;
case PICoutManipulators::ShowCursor:
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = true;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#else
printf("\e[?25h");
#endif
}
break;
case PICoutManipulators::HideCursor:
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = false;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#else
printf("\e[?25l");
#endif
}
break;
case PICoutManipulators::ClearLine:
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
int dx = coord.X;
coord.X = 0;
SetConsoleCursorPosition(__Private__::hOut, coord);
if (dx > 0) {
char * line = new char[dx + 1];
memset(line, ' ', dx);
line[dx] = 0;
printf("%s", line);
delete[] line;
}
SetConsoleCursorPosition(__Private__::hOut, coord);
#else
printf("\e[0G\e[K");
#endif
}
break;
case PICoutManipulators::ClearScreen:
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
/// TODO : wondows ClearScreen !!!
#else
printf("\e[H\e[J");
#endif
}
break;
case PICoutManipulators::SaveContol: saveControls(); break;
case PICoutManipulators::RestoreControl: restoreControls(); break;
default: break;
};
return *this;
}
PICout & PICout::operator <<(PICoutManipulators::PICoutFormat v) {
switch (v) {
case PICoutManipulators::Bin: cnb_ = 2; break;
case PICoutManipulators::Oct: cnb_ = 8; break;
case PICoutManipulators::Dec: cnb_ = 10; break;
case PICoutManipulators::Hex: cnb_ = 16; break;
default: applyFormat(v);
};
return *this;
}
PICout & PICout::operator <<(PIFlags<PICoutManipulators::PICoutFormat> v) {
if (v[PICoutManipulators::Bin]) cnb_ = 2;
if (v[PICoutManipulators::Oct]) cnb_ = 8;
if (v[PICoutManipulators::Dec]) cnb_ = 10;
if (v[PICoutManipulators::Hex]) cnb_ = 16;
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
return *this;
}
#define PIINTCOUT(v) { \
if (!act_) return *this; \
space(); \
if (cnb_ == 10) {\
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v);\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v);\
}\
} else write(PIString::fromNumber(v, cnb_)); \
return *this; \
}
#define PIFLOATCOUT(v) { \
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v, 'g');\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g');\
}\
}\
return *this;
PICout & PICout::operator <<(const PIString & v) {
space();
quote();
write(v);
quote();
return *this;
}
PICout & PICout::operator <<(const char * v) {
if (!act_ || !v) return *this;
if (v[0] == '\0') return *this;
space();
quote();
write(v);
quote();
return *this;
}
PICout & PICout::operator <<(bool v) {
if (!act_) return *this;
space();
if (v) write("true");
else write("false");
return *this;
}
PICout & PICout::operator <<(char v) {
if (!act_) return *this;
space();
write(v);
return *this;
}
PICout & PICout::operator <<(uchar v) {PIINTCOUT(ushort(v))}
PICout & PICout::operator <<(short int v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ushort v) {PIINTCOUT(v)}
PICout & PICout::operator <<(int v) {PIINTCOUT(v)}
PICout & PICout::operator <<(uint v) {PIINTCOUT(v)}
PICout & PICout::operator <<(long v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ulong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(llong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ullong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(float v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator <<(void * v) {
if (!act_) return *this;
space();
write("0x" + PIString::fromNumber(ullong(v), 16));
return *this;
}
PICout & PICout::operator <<(const PIObject * v) {
if (!act_) return *this;
space();
if (v == 0) write("PIObject*(0x0)");
else {
write(v->className());
write("*(0x" + PIString::fromNumber(ullong(v), 16) + ", \"" + v->name() + "\")");
}
return *this;
}
PICout & PICout::operator <<(PICoutSpecialChar v) {
if (!act_) return *this;
switch (v) {
case Null:
if (buffer_) {
(*buffer_) += PIChar();
} else {
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar();
}
break;
case NewLine:
if (buffer_) {
(*buffer_) += "\n";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
}
fo_ = true;
break;
case Tab:
if (buffer_) {
(*buffer_) += "\t";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\t";
}
break;
case Esc:
#ifdef CC_VC
if (buffer_) {
(*buffer_) += PIChar(27);
} else {
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar(27);
}
#else
if (buffer_) {
(*buffer_) += "\e";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\e";
}
#endif
break;
case Quote:
if (buffer_) {
(*buffer_) += "\"";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '"';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
}
break;
};
return *this;
}
PICout & PICout::saveControls() {
if (!act_) return *this;
PRIVATE->cos_.push(co_);
return *this;
}
PICout & PICout::restoreControls() {
if (!act_) return *this;
if (!PRIVATE->cos_.isEmpty()) {
co_ = PRIVATE->cos_.top();
PRIVATE->cos_.pop();
}
return *this;
}
//! \details
//! \~english
//! If it is not a first output and control \a AddSpaces is set space character is put
//! \~russian
//! Добавляет пробел если это не первый вывод и установлен флаг \a AddSpaces
//! \~\sa \a quote(), \a newLine()
PICout & PICout::space() {
if (!act_) return *this;
if (!fo_ && co_[AddSpaces]) {
if (buffer_) {
(*buffer_) += " ";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += " ";
}
}
fo_ = false;
return *this;
}
//! \details
//! \~english
//! If control \a AddQuotes is set quote character is put
//! \~russian
//! Добавляет кавычки если установлен флаг \a AddQuotes
//! \~\sa \a space(), \a newLine()
PICout & PICout::quote() {
if (!act_) return *this;
if (co_[AddQuotes]) {
if (buffer_) {
(*buffer_) += "\"";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '"';
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
}
}
fo_ = false;
return *this;
}
//! \details
//! \~english
//! If control \a AddNewLine is set new line character is put
//! \~russian
//! Добавляет новую строку если установлен флаг \a AddNewLine
//! \~\sa \a space(), \a quote()
PICout & PICout::newLine() {
if (!act_) return *this;
if (co_[AddNewLine]) {
if (buffer_) {
(*buffer_) += "\n";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
}
}
fo_ = false;
return *this;
}
PICout & PICout::write(char c) {
if (!act_) return *this;
if (buffer_) {
buffer_->append(c);
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << c;
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(c);
}
return *this;
}
PICout & PICout::write(const char * str) {
if (!act_ || !str) return *this;
return write(str, strlen(str));
}
PICout & PICout::write(const char * str, int len) {
if (!act_ || !str) return *this;
if (buffer_) {
buffer_->append(PIString(str, len));
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout.write(str, len);
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(PIString(str, len));
}
return *this;
}
PICout & PICout::write(const PIString & s) {
if (!act_) return *this;
if (buffer_) {
buffer_->append(s);
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) stdoutPIString(s);
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
}
return *this;
}
void PICout::stdoutPIString(const PIString & s) {
#ifdef HAS_LOCALE
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
std::cout << utf8conv.to_bytes((char16_t*)&(const_cast<PIString&>(s).front()), (char16_t*)&(const_cast<PIString&>(s).front()) + s.size());
#else
for (PIChar c: s) std::wcout.put(c.toWChar());
#endif
}
void PICout::init() {
#ifdef WINDOWS
if (__Private__::hOut == 0) {
__Private__::hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO sbi;
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
__Private__::dattr = sbi.wAttributes;
}
attr_ = __Private__::dattr;
#endif
id_ = 0;
if ((co_ & NoLock) != NoLock) {
PICout::__mutex__().lock();
}
}
void PICout::applyFormat(PICoutFormat f) {
if (!act_) return;
if (buffer_ || !isOutputDeviceActive(StdOut)) return;
fc_ = true;
#ifdef WINDOWS
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
case PICoutManipulators::Red: attr_ = (attr_ & mask_fore) | FOREGROUND_RED; break;
case PICoutManipulators::Green: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN; break;
case PICoutManipulators::Blue: attr_ = (attr_ & mask_fore) | FOREGROUND_BLUE; break;
case PICoutManipulators::Yellow: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN; break;
case PICoutManipulators::Magenta: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_BLUE; break;
case PICoutManipulators::Cyan: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case PICoutManipulators::White: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case PICoutManipulators::BackBlack: attr_ = (attr_ & mask_back); break;
case PICoutManipulators::BackRed: attr_ = (attr_ & mask_back) | BACKGROUND_RED; break;
case PICoutManipulators::BackGreen: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN; break;
case PICoutManipulators::BackBlue: attr_ = (attr_ & mask_back) | BACKGROUND_BLUE; break;
case PICoutManipulators::BackYellow: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN; break;
case PICoutManipulators::BackMagenta: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_BLUE; break;
case PICoutManipulators::BackCyan: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case PICoutManipulators::BackWhite: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case PICoutManipulators::Default: attr_ = __Private__::dattr; break;
default: break;
}
SetConsoleTextAttribute(__Private__::hOut, attr_);
#else
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case PICoutManipulators::Bold: printf("\e[1m"); break;
case PICoutManipulators::Faint: printf("\e[2m"); break;
case PICoutManipulators::Italic: printf("\e[3m"); break;
case PICoutManipulators::Underline: printf("\e[4m"); break;
case PICoutManipulators::Blink: printf("\e[5m"); break;
case PICoutManipulators::Black: printf("\e[30m"); break;
case PICoutManipulators::Red: printf("\e[31m"); break;
case PICoutManipulators::Green: printf("\e[32m"); break;
case PICoutManipulators::Blue: printf("\e[34m"); break;
case PICoutManipulators::Yellow: printf("\e[33m"); break;
case PICoutManipulators::Magenta: printf("\e[35m"); break;
case PICoutManipulators::Cyan: printf("\e[36m"); break;
case PICoutManipulators::White: printf("\e[37m"); break;
case PICoutManipulators::BackBlack: printf("\e[40m"); break;
case PICoutManipulators::BackRed: printf("\e[41m"); break;
case PICoutManipulators::BackGreen: printf("\e[42m"); break;
case PICoutManipulators::BackBlue: printf("\e[44m"); break;
case PICoutManipulators::BackYellow: printf("\e[43m"); break;
case PICoutManipulators::BackMagenta: printf("\e[45m"); break;
case PICoutManipulators::BackCyan: printf("\e[46m"); break;
case PICoutManipulators::BackWhite: printf("\e[47m"); break;
case PICoutManipulators::Default: printf("\e[0m"); break;
default: break;
}
#endif
}
PIString PICout::getBuffer() {
PIMutexLocker ml(PICout::__mutex__());
PIString ret = PICout::__string__();
return ret;
}
PIString PICout::getBufferAndClear() {
PIMutexLocker ml(PICout::__mutex__());
PIString ret = PICout::__string__();
PICout::__string__().clear();
return ret;
}
void PICout::clearBuffer() {
PIMutexLocker ml(PICout::__mutex__());
PICout::__string__().clear();
}
bool PICout::setOutputDevice(PICout::OutputDevice d, bool on) {
bool ret = devs[d];
devs.setFlag(d, on);
return ret;
}
void PICout::setOutputDevices(PICout::OutputDevices d) {
devs = d;
}
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
return devs[d];
}
PICout PICout::withExternalBuffer(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls) {
PICout c(controls);
c.buffer_ = buffer;
c.id_ = id;
return c;
}