git-svn-id: svn://db.shs.com.ru/pip@400 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
407
src_main/core/picout.cpp
Normal file
407
src_main/core/picout.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Universal output to console class
|
||||
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
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 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 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "piincludes_p.h"
|
||||
#include "picout.h"
|
||||
#include "piconsole.h"
|
||||
#include "pibytearray.h"
|
||||
#include "pistack.h"
|
||||
#include "pistring_std.h"
|
||||
#ifdef WINDOWS
|
||||
# include <windows.h>
|
||||
# include <wincon.h>
|
||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||
#endif
|
||||
|
||||
/*! \class PICout
|
||||
* \brief Class for formatted output similar std::cout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* 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.
|
||||
*
|
||||
* \section PICout_sec1 Features
|
||||
* - insertion spaces between entries
|
||||
* - insertion new line at the end of output
|
||||
* - strings are quoted
|
||||
* - custom output operator can be easily written
|
||||
*
|
||||
* \section PICout_ex0 Usage
|
||||
* \snippet picout.cpp 0
|
||||
*
|
||||
* \section PICout_ex1 Writing your own output operator
|
||||
* \snippet picout.cpp own
|
||||
*/
|
||||
|
||||
PIMutex __PICout_mutex__;
|
||||
PIString __PICout_string__;
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
bool PICout::buffer_ = false;
|
||||
|
||||
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(PIFlags<PICoutControl> controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) {
|
||||
#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
|
||||
__PICout_mutex__.lock();
|
||||
}
|
||||
|
||||
|
||||
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {
|
||||
}
|
||||
|
||||
|
||||
PICout::~PICout() {
|
||||
if (fc_) applyFormat(PICoutManipulators::Default);
|
||||
if (cc_) return;
|
||||
newLine();
|
||||
__PICout_mutex__.unlock();
|
||||
}
|
||||
|
||||
|
||||
PICout PICout::operator <<(const PICoutAction v) {
|
||||
#ifdef WINDOWS
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
COORD coord;
|
||||
CONSOLE_CURSOR_INFO curinfo;
|
||||
#endif
|
||||
switch (v) {
|
||||
case PICoutManipulators::Flush:
|
||||
if (!PICout::buffer_)
|
||||
std::cout << std::flush;
|
||||
break;
|
||||
case PICoutManipulators::Backspace:
|
||||
if (!PICout::buffer_) {
|
||||
#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 (!PICout::buffer_) {
|
||||
#ifdef WINDOWS
|
||||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
curinfo.bVisible = true;
|
||||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25h");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PICoutManipulators::HideCursor:
|
||||
if (!PICout::buffer_) {
|
||||
#ifdef WINDOWS
|
||||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25l");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PICoutManipulators::ClearLine:
|
||||
if (!PICout::buffer_) {
|
||||
#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 (!PICout::buffer_) {
|
||||
#ifdef WINDOWS
|
||||
/// TODO !!!
|
||||
/*GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
|
||||
SetConsoleCursorPosition(__Private__::hOut, ulcoord);
|
||||
FillConsoleOutputAttribute(__Private__::hOut, __Private__::dattr, width * (height + 1), ulcoord, &written);
|
||||
FillConsoleOutputCharacter(__Private__::hOut, ' ', width * (height + 1), ulcoord, &written);*/
|
||||
#else
|
||||
printf("\e[H\e[J");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PICoutManipulators::SaveContol: saveControl(); break;
|
||||
case PICoutManipulators::RestoreControl: restoreControl(); break;
|
||||
default: break;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#define PICOUTTOTARGET(v) {if (PICout::buffer_) __PICout_string__ << (v); else std::cout << (v);}
|
||||
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_))
|
||||
|
||||
|
||||
PICout PICout::operator <<(const char * v) {if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
|
||||
|
||||
PICout PICout::operator <<(const std::string & v) {space(); quote(); if (PICout::buffer_) __PICout_string__ << StdString2PIString(v); else std::cout << (v); quote(); return *this;}
|
||||
|
||||
PICout PICout::operator <<(const bool v) {space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
|
||||
|
||||
PICout PICout::operator <<(const char v) {space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ushort v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const int v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const uint v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const long v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ulong v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const llong v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const float v) {space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const double v) {space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const void * v) {space(); PICOUTTOTARGET("0x") PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const PIObject * v) {
|
||||
space();
|
||||
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
|
||||
else {
|
||||
PICOUTTOTARGET(v->className())
|
||||
PICOUTTOTARGET("*(0x")
|
||||
PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16))
|
||||
PICOUTTOTARGET(", \"")
|
||||
PICOUTTOTARGET(v->name())
|
||||
PICOUTTOTARGET("\")")
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||||
switch (v) {
|
||||
case Null:
|
||||
if (PICout::buffer_) __PICout_string__ << PIChar(0);
|
||||
else std::cout << char(0);
|
||||
break;
|
||||
case NewLine:
|
||||
if (PICout::buffer_) __PICout_string__ << "\n";
|
||||
else std::cout << '\n';
|
||||
fo_ = true;
|
||||
break;
|
||||
case Tab:
|
||||
if (PICout::buffer_) __PICout_string__ << "\t";
|
||||
else std::cout << '\t';
|
||||
break;
|
||||
case Esc:
|
||||
#ifdef CC_VC
|
||||
if (PICout::buffer_) __PICout_string__ << PIChar(27);
|
||||
else std::cout << char(27);
|
||||
#else
|
||||
if (PICout::buffer_) __PICout_string__ << "\e";
|
||||
else std::cout << '\e';
|
||||
#endif
|
||||
break;
|
||||
case Quote:
|
||||
if (PICout::buffer_) __PICout_string__ << "\"";
|
||||
else std::cout << '"';
|
||||
break;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PICout & PICout::saveControl() {
|
||||
PRIVATE->cos_.push(co_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PICout & PICout::restoreControl() {
|
||||
if (!PRIVATE->cos_.isEmpty()) {
|
||||
co_ = PRIVATE->cos_.top();
|
||||
PRIVATE->cos_.pop();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#undef PICOUTTOTARGET
|
||||
#undef PINUMERICCOUT
|
||||
|
||||
PICout & PICout::space() {
|
||||
if (!fo_ && co_[AddSpaces]) {
|
||||
if (PICout::buffer_) __PICout_string__ << " ";
|
||||
else std::cout << ' ';
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout & PICout::quote() {
|
||||
if (co_[AddQuotes]) {
|
||||
if (PICout::buffer_) __PICout_string__ << "\"";
|
||||
else std::cout << '"';
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout & PICout::newLine() {
|
||||
if (co_[AddNewLine]) {
|
||||
if (PICout::buffer_) __PICout_string__ << "\n";
|
||||
else std::cout << std::endl;
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void PICout::applyFormat(PICoutFormat f) {
|
||||
if (PICout::buffer_) 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
|
||||
}
|
||||
|
||||
|
||||
bool PICout::setBufferActive(bool on, bool clear) {
|
||||
PIMutexLocker ml(__PICout_mutex__);
|
||||
bool ret = PICout::buffer_;
|
||||
if (clear) __PICout_string__.clear();
|
||||
PICout::buffer_ = on;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool PICout::isBufferActive() {
|
||||
return PICout::buffer_;
|
||||
}
|
||||
|
||||
|
||||
PIString PICout::buffer(bool clear) {
|
||||
PIMutexLocker ml(__PICout_mutex__);
|
||||
PIString ret = __PICout_string__;
|
||||
if (clear) __PICout_string__.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PICout::clearBuffer() {
|
||||
PIMutexLocker ml(__PICout_mutex__);
|
||||
__PICout_string__.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user