Mirai-Team / mirai-project

C++ library for games making purposes.
Other
3 stars 0 forks source link

Improve Logger #69

Closed Lomadriel closed 9 years ago

Lomadriel commented 9 years ago

We should change how Logger works, instead passing priorities as parameters, we should chain them. At the end of the output the logger will report number of all priorities used.

Example

mp::Logger log("OutputFile_path", "MiraiProject v0.2");
log << mp::Logger::Priority("Whatever you want") << "My message";
log << "My message without any priorities";

instead of

mp::Logger log("OutputFile_path");
log("My Priority") << "My message";  // or
log() << "My message";

And the output will be

MiraiProject v0.2
[Whatever you want] : My Message
My message without any priorities

1 "Whatever you want"

EDIT : see https://github.com/Mirai-Team/mirai-project/issues/69#issuecomment-111738668

CBenoit commented 9 years ago

I agree. But what's the purpose of the second parameter ("MiraiProject v0.2") ?

Lomadriel commented 9 years ago

It's just a message put at the beginning of the file as you can see in the output. Obviously it's optional. And you can also do:

mp::Logger log("OutputFile_path");
log <<  "MiraiProject v0.2";

It's just an easier way to do it.

CBenoit commented 9 years ago

I see… why not, but I doubt it's really useful. Could you post the header file before starting writing the whole .cpp code ?

Lomadriel commented 9 years ago

On second thought, we should not open the file in the Constructor. If the constructor doesn't manage to open the file. The next instruction will cause a segmentation fault. Indeed we can't check if the file is open since the file is open in the constructor.

mp::Logger log("file.txt"); // doesn't manage to open the file.
log << "My message"; // Segmentation fault

A solution is to check if the file is open for each instruction. However I think it will be better if we add a init() method like that:

mp::Logger log("file.txt");
if (!log.init())
    return; // or something else that stops the program
log << "My message";
CBenoit commented 9 years ago

I agree. And add a way to log flux to multiple streams would be of use as well !

Lomadriel commented 9 years ago

In my opinion, the Logger should inherit of std::ostream or something like that. The user will be able to use rdbuf to redirect the stream, and naturally we have to add a stream that can redirect the messages to several other streams

Lomadriel commented 9 years ago

and naturally we have to add a stream that can redirect the messages to several other streams

I found a way which might work. It's a solution based on the std::streambuf with the std::ios::rdbuf method.

Lomadriel commented 9 years ago

I will implement this stream like this:


class DoubleStream : public std::streambuf
{
    public:
        DoubleStream(std::streambuf* streambuf1, std::streambuf* streambuf2);
        ~DoubleStream();

    protected:
        void imbue(const std::locale& loc);
        int oveflow(int c = EOF);
        int sync();
    private:
        std::vector<char>   m_buffer; // Will have a fixed size of 128 or 256 bytes

        std::streambuf* m_streambuf1;
        std::streambuf* m_streambuf2;
}

// Usage

int main()
{
    std::ofstream myFile("myFile.txt");
    std::streambuf* backup = std::cout.rdbuf(); // Essential
    DoubleStream mystream(backup, myFile.rdbuf());

    std::cout.rdbuf(&mystream);
    std::cout << "My message" << std::endl;
    std::cout.rdbuf(backup); // the backup is essential for this step otherwise you will get a segmentation fault when mystream is destroyed
    std::cout << 3.16 << std::endl;
    myFile.close();
    return 0;
}

Output in console:

My message
3.16

Output in myfile.txt

My message

For more information, I recommend you to read this: http://www.cplusplus.com/reference/streambuf/streambuf/sync/ http://www.cplusplus.com/reference/streambuf/streambuf/overflow/ http://www.cplusplus.com/reference/streambuf/streambuf/imbue/

CBenoit commented 9 years ago

Seems nice to me. But why is it limited to only two streams ? Is there any particular reason ?

Lomadriel commented 9 years ago

Not really, I can add a support for more than two streams, but I have to add some loops in this case... So in the end if you add many streams, it will slow down the program.

CBenoit commented 9 years ago

This is quite normal. Using many streams slow down anyway.

Lomadriel commented 9 years ago

Done.

Lomadriel commented 9 years ago

Improved logger.

I moved some methods in private label. Updated operator<< method. Added some documentations.