C++ Console Progress Indicator - c++

What would be an easy way of implementing a console-based progress indicator for a task that's being executed, but I can't anticipate how much time it would take?
I used to do this back when I coded in Clipper, and it was only a matter of iterating through the chars '/', '-', '\', '|' and positioning them in the same place.
Any way / links / libs for doing that (or something similar) in C++?
The target for this is *nix environments.
Edits:
changed the title to be more coherent and generic;
added target environment.

A very simple way to do it is to print out a string followed by a '\r' character. That is carriage return by itself and on most consoles, it returns the cursor to the beginning of the line without moving down. That allows you to overwrite the current line.
If you are writing to stdout or cout or clog remember to fflush or std::flush the stream to make it output the line immediately. If you are writing to stderr or cerr then the stream is unbuffered and all output is immediate (and inefficient).
A more complicated way to do it is to get into using a screen drawing library like curses. The Windows consoles have some other ways of setting them for direct screen writing but I don't know what they are.

You could try something like:
void
spinner(int spin_seconds) {
static char const spin_chars[] = "/-\\|";
unsigned long i, num_iterations = (spin_seconds * 10);
for (i=0; i<num_iterations; ++i) {
putchar(spin_chars[i % sizeof(spin_chars)]);
fflush(stdout);
usleep(100000);
putchar('\b');
}
}
Of course, this is non-standard because of the sub-second usleep() and I'm not sure if there is any guarantee that \b erases a character or not, but it works on most platforms. You can also try \r instead if \b doesn't do the trick. Otherwise, try to find a version of curses.
Edit (curses sample)
This should get you started:
#include <curses.h>
#include <unistd.h>
void spinner(int spin_seconds) {
static char const spin_chars[] = "/-\\|";
unsigned long i, num_iterations = (spin_seconds * 10);
for (i=0; i<num_iterations; ++i) {
mvaddch(0, 0, spin_chars[i & 3]);
refresh();
usleep(100000);
}
}
int main() {
initscr(); /* initializes curses */
spinner(10); /* spin for 10 seconds */
endwin(); /* cleanup curses */
return 0;
}
Make sure to link with either -lcurses or -lncurses. That should work on any UNIX alike out there.

Boost has a progress library which can help some of these things

Wow, clipper, perhaps you are talking about the #row,col things built in to the language? (Rhetorical question only...)
You can do simple progress bars with printf: you can leave out the trailing newline. You can obviously begin or end the string with \b in order to overprint characters. It's easy to do the traditional -\|/ kind that way.
I recall that the Eclipse UI guidelines recommended progress indicators regardless of how much you were able to tell about the actual progress. I think theory was that anything is better than nothing and to just do the best you can.
The only trick that you are likely to need is potentially to defeat line buffering. Be sure to fflush(stdout) after each output operation. (Or ostream::flush())

Related

win api readConsole()

I am trying to use Win API ReadConsole(...) and I want to pass in a delimiter char to halt the input from the console.
The below code works but it only stops reading the input on \r\n.
I would like it to stop reading the console input on '.' for instance.
void read(char *cIn, char delim)
{
HANDLE hFile;
DWORD charsRead;
DWORD charsToRead = MAX_PATH;
CONSOLE_READCONSOLE_CONTROL cReadControl;
cReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
cReadControl.nInitialChars = 0;
cReadControl.dwCtrlWakeupMask = delim;
cReadControl.dwControlKeyState = NULL;
DWORD lpMode;
// char cIn[MAX_PATH]; //-- buffer to hold data from the console
hFile = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
GetConsoleMode(hFile,&lpMode);
// lpMode &= ~ENABLE_LINE_INPUT; //-- turns off this flag
// SetConsoleMode(hFile, lpMode); //-- set the mode with the new flag off
bool read = ReadConsole(hFile, cIn, charsToRead * sizeof(TCHAR), &charsRead, &cReadControl);
cIn[charsRead - 2] = '\0';
}
I know there are other easy ways to do this but I am just trying to understand some of the win api functions and how to use them.
Thank you.
I saw this question and assumed it would be trivial, but spent the last 30 minutes trying to figure it out and finally have something.
That dwCtrlWakeupMask is pretty poorly documented in CONSOLE_READCONSOLE_CONTROL. MSDN says "A user-defined control character used to signal that the read is complete.", but why is it called mask? Why is it a ULONG instead of a TCHAR or something like that? I tried feeding it chars and wchars and nothing happened, so there must be more to the story.
I took to the web searching for that particular variable and found this link:
https://groups.google.com/forum/#!topic/golang-codereviews/KSp37ITmcUg It is a random Go library coder asking for help and the answer is that tab is 1 << '\t'. I tried it, and it works!
So, for future web searchers, dwCtrlWakeupMask is a bitmask of ASCII control characters that will cause ReadConsole to return. You can | together as many 1 << ctrl_chars as you like... but it cannot be arbitrary characters, since it is a bitmask in a 32 bit value, only the chars 1-31 (inclusive) are possible (this group btw is called control characters, it includes things like tab, backspace, bell; things that do not represent printable characters per se).
Thus, this mask:
cReadControl.dwCtrlWakeupMask = (1 << '\t') | (1 << 0x08);
Will cause ReadConsole to return when tab (\t) OR when backspace (0x08) is pressed.
The characters represented by ctrl+ some_ascii_value are the number of that letter in the english alphabet, starting at a == 1. So, ctrl+d is 4, and ctrl+z is 26.
Therefore, this will return when the user hits ctrl+d or ctrl+z:
cReadControl.dwCtrlWakeupMask = (1 << 4) | (1 << 26);
Note that the Linux terminal driver also returns on read when the user hits ctrl+d so this might be a nice compatibility thing.
I believe the point of this argument is to allow easier tab-completion in processed input mode; otherwise, you'd have to turn processed input off and process keys one by one to do that. Now you don't have to.... though tbh, I still prefer taking my input with ReadConsoleInput for interactive programs since you get much better control over it all.
But while there are a lot of other ways to do what you want - and using . as a delimiter is impossible here, since it has a value >= 32, so you need to do it yourself... understanding what this does is interesting to me anyway, and there's scarce resources on the web so I'm writing this up just for future reference.
Note that this does not appear to work in wineconsole so be sure you are on a real Windows box to test it out.
Now, dwControlKeyState is actually set BY the function. Your value passed in is ignored (at least as far as I can tell), but you can inspect it for the given flags when the function returns. So, for example, after calling ReadConsole and hitting the key, it will be 32 if your numlock was on. It will be 48 is numlock was on and you pressed shift+tab (and had numlock on). So you test it after the function returns.
I typically like MSDN docs but IMO they completely dropped the ball on explaining this parameter!
You will find this code ridiculous. It is most likely the only way to do this. If you have to adapt to use ReadFile later it is the only way that doesn't consume more input.
Most of the time you don't really want ReadConsole at all you want ReadFile on the standard input handle, but I digress.
char *cInptr = cIn;
do {
bool read = ReadConsole(hFile, cInptr, sizeof(TCHAR), &charsRead, &cReadControl);
if (read) cInptr += charsRead;
} while (read && charsRead > 0 && cInptr[-1] && cInptr[-1] != '.');
I might have too many tests in the loop due to being paranoid. I'm not inclined to look up all predicates to determine which are implied by the contract of ReadConsole.

Capturing child stdout to a buffer

I'm developing a cross platform project currently. On windows i had a class that ran a process/script (using a commandline), waited for it to end, and read everything from it's stdout/stderr to a buffer. I then printed the output to a custom 'console'. Note: This was not a redirection of child stdout to parent stdout, just a pipe from child stdout to parent.
I'm new to OSX/unix-like api's but i can understand the canonical way of doing something like this is forking and piping stdouts together. However, i dont want to redirect it to stdout and i would like to capture the output.. It should work pretty much like this (pseudocode, resemblance with unix functions purely coincidental):
class program
{
string name, cmdline;
string output;
program(char * name, char * cmdline)
: name(name), cmdline(cmdline) {};
int run()
{
// run program - spawn it as a new process
int pid = exec(name, cmdline);
// wait for it to finish
wait(pid);
char buf[size];
int n;
// read output of program's stdout
// keep appending data until there's nothing left to read
while (read(pid, buf, size, &n))
output.append(buf, n);
// return exit code of process
return getexitcode(pid);
}
const string & getOutput() { return output; }
};
How would i go about doing this on OSX?
E:
Okay so i studied the relevant api's and it seems that some kind of fork/exec combo is unavoidable. Problem at hand is that my process is very large and forking it really seems like a bad idea (i see that some unix implementations can't do it if the parent process takes up 50%+ of the system ram).
Can't i avoid this scheme in any way? I see that vfork() might be a possible contender, so maybe i could try to mimic the popen() function using vfork. But then again, most man pages state that vfork might very well just be fork()
You have a library call to do just that: popen. It will provide you with a return value of a file descriptor, and you can read that descriptor till eof. It's part of stdio, so you can do that on OSX, but other systems as well. Just remember to pclose() the descriptor.
#include <stdio.h>
FILE * popen(const char *command, const char *mode);
int pclose(FILE *stream);
if you want to keep output with absolutely no redirection, the only thing we can think of is using something like "tee" - a command which splits the output to a file but maintains its own stdout. It's fairly easy to implement that in code as well, but it might not be necessary in this case.

How to get displayed width of a string?

When you have non-fixed width characters (such as \t) in a string , or escape codes, such as those for ANSI color (such as \1xb[31m), these characters add to the .length() of an std::string, but do not add to the displayed length when printed.
Is there any way in C++ to get the displayed width of a string in *nix?
For instance:
displayed_width("a\tb") would be 4 if the displayed tab width is 2
displayed_width("\1xb[33mGREEN") would be 5
Most commonly, a tab asks the terminal program to move the cursor to a column that's a multiple of 8, though many terminal programs let you configure that. With such behaviour, how much width a tab actually adds depends on where the cursor was beforehand relative to the tab stops. So, simply knowing the string content is not enough to calculate a printable width without some assumption or insight regarding prior cursor placement and tab stops.
Non-printable codes also vary per terminal type, though if you only need ANSI colour then that's pretty easy. You can move along the string counting characters; when you see an ESCAPE skip through to the terminating m. Something like (untested):
int displayed_width(const char* p)
{
int result = 0;
for ( ; *p; ++p)
{
if (p[0] == '\e' && p[1] == '[')
while (*p != 'm')
if (*p)
++p;
else
throw std::runtime_error("string terminates inside ANSI colour sequence");
else
++result;
}
return result;
}
Nothing built in. The "displayed width" of the tab character is an implementation detail, as are console escape sequences. C++ doesn't care about platform-specific things like that.
Is there something in particular you're trying to do? We may be able to suggest alternatives if we know what particular task you're working on.
Not with standard methods to my knowledge. C++ does not know about terminals.
My guess would be to use NCURSES for that. Dunno if boost has something up the sleeve for that though.
Display length on what device? A console that uses a fixed-width font? A window that uses a proportional font? This is highly device-dependent question. There is no fixed answer. You will have to use the tools associated with the target output device.

Boost: how to create a thread so that you can control all of its standard output, standard errors?

I create a win32 console app in C++. I use some API (not mine, and I can not modify its sources). It Is written so that it writes some of its info onto console screen not asking... each time I call it (48 times per second) So I want to put it into some thread and limit its output capabilities, but I need to get notified when that thread will try to output some message which is important for me. I have message text in standard string. How to do such thing in C++ using boost?
Here's a crazy idea:
If the lib is using cout/cerr, you could replace the streambuf of these global variables with an implementation of your own. It would, on flush/data, check some thread-local variable to see if the data came from the thread that calls the library, then route it somewhere else (i.e. into a std::string/std::ostringstream) instead of to the regular cout/cerr streambufs. (Which you should keep around.)
If it's using c's stdout/stderr, I think it'd be harder to do properly, but it might be doable still. You'd need to create some pipes and route stuff back and forth. More of a C/unixy question then, which I don't know that much about... yet. :)
Hope it helps.
That feature does not exist in Boost. You can, however, use _dup2 to replace the standard out descriptor:
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <iostream>
#include <windows.h>
int main()
{
HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (0 == SetStdHandle(STD_OUTPUT_HANDLE, h)) {
std::fprintf(stderr, "`SetStdHandle` failed with error %d\n", (int)GetLastError());
return EXIT_FAILURE;
}
int h_desc = _open_osfhandle((long)h, 0);
_dup2(h_desc, STDOUT_FILENO);
std::printf("test\r\n"); // This actually writes to `h`.
std::fflush(stdout);
std::cout << "another test" << std::endl; // Also writes to `h`
CloseHandle(h);
return EXIT_SUCCESS;
}
Essentially what this trick does is allow you to redirect all writes to stdout, std::cout, and GetStdHandle(STD_OUTPUT_HANDLE) to a writable handle of your choosing (h). Of course, you can use CreatePipe to create the writable handle (h) and read from the readable end in another thread.
EDIT: If you are looking for a cross-platform solution, note that this trick is even easier on POSIX-compatible systems because dup2 is a standard function in unistd.h and "writable handles" are already descriptors.
I cannot think of a way to achieve in Boost what you want, as the problem is described.
However, this API behaviour is very perplexing. Spitting out reams of output to the console is a bit antisocial. Are you using a Debug build of the API library? Are you sure there's no way to configure the API such that it outputs this data to a different stream, so that you can filter it without capturing the entire standard output? Is there a way to reduce the amount of output, so that you only see the important events you care about?
If you really need to capture standard output and act on certain strings (events) of interest, then Win32 provides ways to do this, but I'd really take a hard look at whether this output can be modified to meet your needs before resorting to that.

Redirect both cout and stdout to a string in C++ for Unit Testing

I'm working on getting some legacy code under unit tests and sometimes the only way to sense an existing program behavior is from the console output.
I see lots of examples online for how to redirect stdout to another file in C++, but is there a way I can redirect it to an in-memory stream so my tests don't have to rely on the disk?
I'd like to get anything that the legacy code sends to stdout into a std::string so I can easily .find on the output.
Edit
The legacy code is so bad that it users a mixture of cout << .. and printf. Here is what I have so far:
void TestSuite::setUp(void)
{
oldStdoutBuf = std::cout.rdbuf();
std::cout.rdbuf(consoleOutput.rdbuf());
}
void TestSuite::tearDown(void)
{
std::cout.rdbuf(oldStdoutBuf);
}
The problem is that this does not capture output using printf. I would like something that gets both. Any ideas?
std::stringstream may be what you're looking for.
UPDATE
Alright, this is a bit of hack, but maybe you could do this to grab the printf output:
char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout);
setbuf(stdout, huge_string_buffer);
Note you should use "/dev/null" for linux instead of "NUL". That will rapidly start to fill up huge_string_buffer. If you want to be able to continue redirecting output after the buffer is full you'll have to call fflush(), otherwise it will throw an error. See std::setbuf for more info.
You can use freopen(..., stdout) and then dump the file into memory or a std::string.
This may be an alternative:
char bigOutBuf[8192];
char savBuf[8192];
fflush(stdout);
setvbuf(stdout,bigOutBuf,IOFBF,8192);//stdout uses your buffer
//after each operation
strncpy(savBuf,bigOutBuf,8192);//won't flush until full or fflush called
//...
//at long last finished
setbuf(stdout,NULL);//reset to unnamed buffer
This just intercepts the buffered output, so still goes to console or wherever.
Hope this helps.
Try sprintf, that's more efficient.
int i;
char str[] = "asdf";
char output[256];
sprintf(output, "asdfasdf %s %d\n", str, i);