The Napkin Trace Library

Author: Shunsuke Sogame
Contact: pstade.mb@gmail.com
License:Distributed under the Boost Software License Version 1.0
Version: 0.90.5

"But I cleaned them with my napkin."

—Dr. Nick

Table of Contents

1   Introduction

Napkin is the simple header-only logging library which provides generic reference-like type to output devices:

napkin::ostream os;

os.reset(std::cout);
os << "to cout:" << 1 << '\n';

os.reset(std::wcout);
os << "to wcout";

std::ofstream fout("log.txt");
os.reset(fout);
os << "to file:" << 3.14;

os << boost::format("%2% %1%")
    % "boost" % "using";

std::stringstream sout;
os.reset(sout);
os << "to string stream:" << 'x';

os.reset(napkin::dout);
os << "to debugger:" << sout.str();

os.reset(napkin::nout);
os << "to trash box";

std::vector<char> vout;
os.reset(vout);
os << "to sequence";

std::string strout;
os.reset(strout);
os << "to string";

All the types, functions and objects are defined in namespace pstade::napkin.

2   Requirements

3   Tested Under

4   Quick Start

  1. Include the Napkin header:

    #include <iostream> // cout
    #include <pstade/napkin.hpp>
    
    void quick_start()
    {
        using namespace pstade;
  2. Initialize ostream:

        napkin::ostream os(std::cout);
  3. Call operator<<:

        os << "hello, napkin";
    }

5   Basic Concepts

5.1   String

A String is a null-terminated const char *.

5.2   String Outputable

A StringOutputable is any out that either of the following expression is valid:

out << psz;
pstade_napkin_extension::pstade_napkin_(pstade_napkin_extension::output(), out, psz);

, where psz is a String. It is unsurprising that many types conform to this simple concept; even afxDump.

5.3   WideString

A WideString is a null-terminated const wchar_t *.

5.4   WideString Outputable

A WideStringOutputable is any out that either of the following expression is valid:

out << psz;
pstade_napkin_extension::pstade_napkin_(pstade_napkin_extension::output(), out, psz);

, where psz is a WideString.

5.5   Output Streamable

This concept comes from Boost.LexicalCast; an OutputStreamable is any type that operator<< is defined that takes a std::ostream or std::wostream object on the left hand side and an instance of the argument type on the right. That means if you have already defined operator<< of your class, Napkin can work with it.

6   Classes

6.1   ostream

ostream is the generic reference-like type to String Outputable objects. The valid expressions are:

ostream os(out);
os.reset(out);
os = out; // is the same as os.reset(out).
bool b = os; // b is true iif os holds a stream.
os << stm;
os << stm0 << stm1 << ... << stmN;

, where os is a ostream object, out is a String Outputable object and stm is a Output Streamable object.

ostream conforms to also Default Constructible and Assignable:

using namespace pstade;

napkin::ostream os1(std::cout);
os1 << "constructor style\n";

napkin::ostream os2;
os2.reset(std::cout);
os2 << "reset style\n";

napkin::ostream os3 = os2;
os3 << "copy\n";

napkin::ostream os4;
os4.reset(os3);
os4 << "os3 is StringOutputable.\n";

Notice that ostream is of course a model of String Outputable, because a String is Output Streamable by definition.

6.2   wostream

wostream is the generic reference-like type to WideString Outputable objects. The valid expressions are:

wostream os(out);
os.reset(out);
os = out; // is the same as os.reset(out).
bool b = os; // b is true iif os holds a stream.
os << stm;
os << stm0 << stm1 << ... << stmN;

, where os is a ostream object, out is a String Outputable object and stm is a Output Streamable object. The usage is the same as above.

6.3   lock_ostream

lock_ostream makes a String Outputable thread-safe:

napkin::lock_ostream los;

void simple_thread()
{
    los << "lock1\n";
}

void test()
{
    los.reset(std::cout);
    boost::thread thrd(&simple_thread);
    los << "lock2\n";
}

Except for not Assignable, the valid expression and usage is same as ostream. Note that you must build Boost.Thread and include explicitly <pstade/napkin/lock_ostream.hpp>.

6.4   lock_wostream

lock_wostream makes a WideString Outputable thread-safe. Except for not Assignable, the valid expression and usage is same as wostream.

7   Predefined String Outputables

7.1   nout

nout is the object that conforms to both String Outputable and WideString Outputable. nout throws out all the inputs, which is usable if you want to temporarily turn off a logging.

7.2   dout

dout is the object that conforms to both String Outputable and WideString Outputable. dout outputs strings by using ::OutputDebugString. This works only under Windows, so that you must explicitly include the header <pstade/napkin/dout.hpp>.

7.3   Standard Containers

Napkin customizes the standard Back Insertion Sequences by using the second valid expression of String Outputable or WideString Outputable concept. If seq::value_type is convertible to char, the seq is a model of String Outputable, and if seq::value_type is convertible to wchar_t, the seq is a model of WideString Outputable, where seq is a type Back Insertion Sequence.

8   Define your own String Outputable

As an example, let's look into dout type definition:

struct dout_type
{
    void operator<<(const TCHAR *psz)
    {
        ::OutputDebugString(psz);
    }
};

Pretty simple.

9   Remove Side-effects

Though Napkin provides nout, you might want to remove all the side-effects under the release compilation. An easy solution is maybe something like:

#include <pstade/debug.hpp> // for the macros

void remove_side_effects()
{
    using namespace std;
    using namespace pstade;

    napkin::ostream os;

    PSTADE_DEBUG_EXPR(os).reset(cout);
    PSTADE_DEBUG_EXPR(os) << "Removed under release compilation\n";

    PSTADE_DEBUG_BLOCK {
        basic_ofstream< char, char_traits<char> > fout("debug.log");
        os.reset(fout);
        os << "'#if !defined(NDEBUG)' is easier!?";
    }
}

10   Points of Interest

As mentioned above, String Outputable concept is simple. You can chain, broadcast or add time information anyway you like. Napkin could be a building block of your logging strategy.

Regardless of its flexibility, Napkin's implementaion is very small. Napkin only makes use of Boost.LexicalCast, which makes use of std::stringstream.

11   References

12   Release Notes

12.1   Version 0.90.0

  • Initial version released.

12.2   Version 0.90.1

12.3   Version 0.90.2

  • Removed pointer style.

12.4   Version 0.90.3

12.5   Version 0.90.4

  • Ported to Boost v1.34.

12.6   Version 0.90.5