[Dec '10] Coming soon: Pantheios.Net. The same technology that allows Pantheios (C++) to be robust, succinct, extensible and highly efficient, applied to the .NET platform. Watch this space ... (or get in contact)

Pantheios

 Pantheios

 

Tutorials: Code

Using Pantheios in application C++ code is extremely simple. The syntax of all function suites follow the same form, which is to say that log statement elements are passed as (comma-separated) arguments to the requisite function, as in:
  pantheios::log_CRITICAL("abc", def, "ghi", pantheios::integer(j), "klm");
or
  pantheios::log(pantheios::critical, "abc", def, "ghi", pantheios::integer(j), "klm");
The Pantheios application layer is generic, that is to say that it accepts any types (with restrictions as described below).

Fundamentally (in the core), Pantheios understands only (slices of) character strings. All other types have to be converted to this form. To use Pantheios it is best to understand how the library treats different types to provide the generic support. There are four sets of argument types to consider:
  1. Types for which string access shims are defined
  2. Numeric and pointer types
  3. Types for which string access shims are not defined
1. Types for which string access shims are defined.

Out of the box, Pantheios comes with string access shims (via the requisite STLSoft header files) defined for the following types:
  • char[]
  • char const*
  • std::string
  • std::exception
  • struct tm const&
  • struct tm const*
  • CComBSTR (if compiling with ATL)
  • CWindow (if compiling with ATL)
  • GUID (if compiling with COM)
  • VARIANT (if compiling with COM)
  • CWnd (if compiling with MFC)
  • CString (if compiling with MFC)
  • CListBox (if compiling with MFC)
  • CListCtrl (if compiling with MFC)
  • CListView (if compiling with MFC)
  • struct dirent const& (if compiling on UNIX)
  • struct dirent const* (if compiling on UNIX)
  • HWND (if compiling on Win32)
  • LSA_UNICODE_STRING (if compiling on Win32)
  • FILETIME (if compiling on Win32)
  • SYSTEMTIME (if compiling on Win32)
Thus, a log statement containing any of these types is implicitly supported by Pantheios. For example, on UNIX, we can write the following:
  #include <pantheios/pantheios.hpp>

  std::string      s1;
  std::exception   x;
  char             s2[10];
  struct tm*       t = . . .;
  struct dirent*   d = . . .;

  pantheios::log(pantheios::critical, s1, x, s2, t, d);
On Windows, we can write the following:
  #include <pantheios/pantheios.hpp>

  std::string      s1;
  std::exception   x;
  char             s2[10];
  struct tm*       t = . . .;
  HWND             hwnd = . . .;
  FILETIME         ft;
  SYSTEMTIME       st;

  pantheios::log(pantheios::critical, s1, x, s2, t, hwnd, ft, st);
Furthermore, string access shims for all types for which a meaningful string representation may be elicited are also defined for components in the following libraries: This means that the components from these libraries are also implicitly compatible with Pantheios.

2. Numeric and pointer types.

Numeric and pointer types and untyped memory are not implicitly compatible with the Pantheios application layer. However, they may be made compatible by use of the Pantheios inserter types integer, pointer and real, as follows:
  #include <pantheios/pantheios.hpp>
  #include <pantheios/inserters/integer.hpp>
  #include <pantheios/inserters/pointer.hpp>
  #include <pantheios/inserters/real.hpp>

  short s;
  int   i;
  long  l;
  float f;
  void* p;

  pantheios::log_NOTICE("short=", pantheios::integer(s)
                      , " int=", pantheios::integer(i)
                      , " long=", pantheios::integer(l)
                      , " float=", pantheios::real(f)
                      , " ptr=", pantheios::pointer(p));
Width, radix and prefixing is controlled by the second, defaulted, parameter to the constructors of the three types, as follows:
  int i = 255;

  pantheios::integer(i, pantheios::fullHex); // yields "0xff"
and
  void* i = reinterpret_cast<void*>(255);

  pantheios::pointer(i, 8 | pantheios::fullHex); // yields "0x000000ff"
3. Types for which string access shims are not defined.

If you pass an instance of a type for which string access shims are not defined to a Pantheios application layer function, you will receive a compilation error:
  class Point
  {
  public:
    Point(int x, int y)
      : x(x)
      , y(y)
    {}

  public:
    int   x;
    int   y;
  };

  Point point(10, 20);

  pantheios::log_ERROR(point); // Error: none of the 17 overloads of 'c_str_len_a' can convert parameter 1 from type 'X'
There are several ways to log instances of such types:
  1. Write explicit conversion code in your application code.

      if(pantheios::isSeverityLogged(pantheios::error))
      {
        pantheios::log_ERROR("Point: {", point.x, ", ", point.y, "; area=", point.x * point.y, "}");
      }
    

  2. Write explicit conversion function to use in log statements.

      std::string point_to_string(Point const& point)
      {
        char    buff[101];
    
        ::sprintf(&buff[0], "{%d, %d; area=%d", point.x, point.y, point.x * point.y);
    
        return buff;
      }
    
    This can be passed as part of the log statement:
      pantheios::log_ERROR("Point: ", point_to_string(point));
    

  3. Define string access shims for the type.

    Option 1 is verbose and error prone. Option 2 is inefficient, especially in the case when the ERROR severity is not being logged. A better, and more portable, solution is to define string access shims for the Point type:
    namespace stlsoft
    {
      inline stlsoft::shim_string<char> c_str_data_a(Point const& point)
      {
        stlsoft::shim_string<char> s(101);
    
        int cch = ::sprintf(s, "{%d, %d; area=%d", point.x, point.y, point.x * point.y);
    
        s.truncate(static_cast<size_t>(cch));
    
        return s;
      }
      inline size_t c_str_len_a(Point const& point)
      {
        char buff[101];
    
        return static_cast<size_t>(::sprintf(&buff[0], "{%d, %d; area=%d", point.x, point.y, point.x * point.y));
      }
    
    } // namespace stlsoft
    
    In this case, the type can be passed directly to the log statement:
      pantheios::log_ERROR("Point: ", point);
    
    Note: There is a slight inefficiency in this case in that c_str_len_a invokes sprintf() in order to ascertain the exact length of the point. In a real scenario we would use an algorithm to calculate the resultant string length without incurring the cost of a call to sprintf().

  4. Define an inserter class for the type.

    The inserter class should use lazy evaluation, such that it only performs the conversion, once, when the first one of either its data() or length() methods is called.
      class point_inserter
      {
        point_inserter(Point const& point)
          : m_point(point)
          , m_length(0)
        {
          m_value[0] = '\0';
        }
    
        char const* data() const
        {
          if('\0' == m_value[0])
          {
            construct_();
          }
    
          return m_value;
        }
        size_t     length() const
        {
          if('\0' == m_value[0])
          {
            construct_();
          }
    
          return m_length;
        }
    
      private:
        void construct_() const
        {
          const_cast<point_inserter*>(this)->construct_();
        }
        void construct_()
        {
          assert('\0' == m_value[0]);
          assert(0 == m_length);
    
          m_length = static_cast<size_t>(::sprintf(&m_value[0], "{%d, %d; area=%d", point.x, point.y, point.x * point.y));
        }
    
      private:
        Point const&  m_point;
        size_t        m_length;
        char          m_value[101];
      };
    
      namespace stlsoft
      {
        inline char const* c_str_data_a(point_inserter const& pi)
        {
          return pi.data();
        }
        inline size_t c_str_len_a(point_inserter const& pi)
        {
          return pi.length();
        }
      }
    
    This can be passed as part of the log statement:
      pantheios::log_ERROR("Point: ", pointer_inserter(point));
    
    Although this is quite a bit of code, it offers the most efficient solution and, once written, such classes can form part of a growing library of inserters that can be used in arbitrary projects.


See also

  • Essentials - essential facts you need to know about Pantheios to get up and running.
  • Pantheios Architecture - introduction to the four parts of the Pantheios architecture: Application Layer, Core, Front-end, Back-ends.
  • Downloads - download the Pantheios library (source and binaries), samples, tools and dependent projects.
  • Tutorials - tutorials on using the Pantheios library.
  • Related Material - read up on the concepts of Shims & Type Tunneling, on the STLSoft auto_buffer class, on namespace aliasing, and more ...
  • API Documentation - once you've familiarised yourself with Pantheios via the tutorials, use the online documentation for fine details on the API functions and types.
  • Project Members - see who is implementing Pantheios, and how you can help out.
  • Performance - performance tests, which demonstrate the claimed peerless performance of Pantheios.
  • Future Directions - features that are anticipated/planned, but not yet implemented.
 

Links

Support This Project

Copyright (c) 1999-2010 Synesis Software Pty Ltd

Valid XHTML 1.0 Transitional