ostream listeners

I'd like to make a logger for my GUI application. I currently use std::cout and std::cerr, but I'd like to replace these with an arbitrary buffer which isn't connected to stdout or stderr. My requirements are:

1. On the user-side, the usage should be identical to any ostream object (including support for std::endl).

2. When std::flush is received, it "signals" my logger so I can run this line of code:
LogWindow->setText( mybuf.str() )

I need an idea for how this can be done. I think I need to extend a std::basic_stringbuf<char>, but which virtual method do I need to implement in order to print to my custom window?

My first attempt is this. I'm testing with std::cout, but the output is empty and running in the debugger doesn't trigger a breakpoint in my sync() method.
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
#include <ostream>
#include <iostream>

class MyBuffer : public std::streambuf
{
public:
    int sync()
    {
        for (char* c = pbase(); c != epptr(); c = pptr())
        {
            //LogWindow->setText( c )
            std::cout << c;
            pbump(1);
        }
        return 0;
    }
};

int main()
{

    MyBuffer mybuf;
    std::ostream dout(&mybuf);

    dout << "Hello" << std::endl;
}


Last edited on
Definitely interesting stuff you have there. I'm running it through a debugger to see what I can do with it.

I'm not looking to re-direct std::cout, cerr, clog. I'm looking to implement my own ostream objects (I have more than 3 categories of windows which outputs will fit into. One for script outputs, one for developer outputs, one for processing outputs, and one for a LaTeX plugin).

While running a skeleton of your Debug.hpp, I had some fully business where pbase() and pptr() were always returning NULL. I checked it in the synch and overflow overrides so I'm not sure why that would happen.
If you don't set the three streambuf pointers in your buffer's constructor (as in the example in the original post), they will be null and no output will take place.

I've found boost.iostream library to be an easy gateway to writing custom streams, did you check it out? http://www.boost.org/doc/libs/release/libs/iostreams/doc/index.html
Thanks guys, now I know what's going on. First I tried to set the internal buffers (who's names aren't published, but I found the gcc implementation names in the header), but then I found setp() from LB's implementation. I definately still have problems with my overflow case, but I'm getting closer. I don't think I need further hints.

Thanks all (code so far is below).

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
#include <ostream>
#include <iostream>
#include <cassert>
#include <vector>
#include <sstream>

class MyBuffer : public std::streambuf
{
    char* buffer;
public:
    MyBuffer(std::size_t buff_sz = 256)
    {
        buffer = new char[buff_sz];
        setp(buffer, buffer + buff_sz);
    }

    ~MyBuffer()
    {
        delete[] buffer;
    }

    int overflow(int ch)
    {
        if(ch != traits_type::eof())
        {
            assert(std::less_equal<char *>()(pptr(), epptr()));

            *pptr() = ch;
            pbump(1);

            sync();
        }
        return traits_type::eof();
    }

    int sync()
    {
        std::stringstream out;

        for(char *p = pbase(), *e = pptr(); p != e; ++p)
        {
            out << *p;
        }

        std::ptrdiff_t n = pptr() - pbase();
        pbump(-n);

        std::cout << pbase();
        std::cout.flush();

        return 0;
    }
};

int main()
{
    MyBuffer mybuf (10);
    std::ostream dout(&mybuf);

    dout << "12345" << std::endl;
    dout << "12345678901234567890" << std::endl;
    dout << "abcdefghijklmnopqrst" << std::endl;
    dout << "uvwxyz" << std::endl;
}
Last edited on
Just FYI I did not write the streambuffer in the code I linked ;)
Got it!

Line 48 above std::cout << pbase(); should have been std::cout << out.str();. Stupid mistake! That's what I get for drinking several bottles of 11% beer and coding at 2am.
Topic archived. No new replies allowed.