cpp/example_cpp_custom_type_1/example_cpp_custom_type_1.cpp

Demonstrates four techniques for logging custom types:

00001 /* /////////////////////////////////////////////////////////////////////////////
00002  * File:        examples/cpp/example_cpp_custom_type_1/example_cpp_custom_type_1.cpp
00003  *
00004  * Purpose:     C++ example program for Pantheios. Demonstrates:
00005  *
00006  *                - use of explicit conversion code for custom type
00007  *                - definition of specific conversion function for custom type
00008  *                - definition of string access shims for custom type
00009  *                - definition of inserter class for custom type
00010  *                - use of pantheios::puts() in bail-out conditions
00011  *
00012  * Created:     31st August 2006
00013  * Updated:     2nd September 2006
00014  *
00015  * www:         http://www.pantheios.org/
00016  *
00017  * License:     This source code is placed into the public domain 2006
00018  *              by Synesis Software Pty Ltd. There are no restrictions
00019  *              whatsoever to your use of the software.
00020  *
00021  *              This software is provided "as is", and any warranties,
00022  *              express or implied, of any kind and for any purpose, are
00023  *              disclaimed.
00024  *
00025  * ////////////////////////////////////////////////////////////////////////// */
00026 
00027 #include <stlsoft/stlsoft.h>
00028 #if defined(STLSOFT_COMPILER_IS_GCC) && \
00029     __GNUC__ < 4
00030 // There's something wrong with GCC, so we have to fwd declare these things
00031 # include <stlsoft/string/shim_string.hpp>
00032 class Person;
00033 class Person_inserter;
00034 namespace stlsoft
00035 {
00036   char const *c_str_data_a(Person_inserter const &pi);
00037   size_t c_str_len_a(Person_inserter const &pi);
00038   stlsoft::basic_shim_string<char, 24> c_str_data_a(Person const &person);
00039   size_t c_str_len_a(Person const &pi);
00040 
00041 } // namespace stlsoft
00042 #endif /* compiler */
00043 
00044 
00045 /* Pantheios Header Files */
00046 #include <pantheios/pantheios.hpp>                  // Pantheios C++ main header
00047 #include <pantheios/inserters/integer.hpp>          // for pantheios::integer
00048 #include <pantheios/assert.h>
00049 
00050 /* STLSoft Header Files */
00051 #include <stlsoft/conversion/integer_to_string.hpp> // for stlsoft::integer_to_string
00052 #include <stlsoft/memory/auto_buffer.hpp>           // for stlsoft::auto_buffer
00053 #include <stlsoft/string/shim_string.hpp>           // for stlsoft::shim_string
00054 
00055 /* Standard C/C++ Header Files */
00056 #include <exception>                                // for std::exception
00057 #include <string>                                   // for std::string
00058 #include <stdlib.h>                                 // for exit codes
00059 
00060 /* ////////////////////////////////////////////////////////////////////////// */
00061 
00062 class Person
00063 {
00064 private:
00065   typedef std::wstring string_type;
00066 
00067 public:
00068   Person(wchar_t const *forename, wchar_t const *surname, unsigned age)
00069     : m_forename(forename)
00070     , m_surname(surname)
00071     , m_age(age)
00072   {}
00073 
00074 public:
00075   string_type const &forename() const
00076   {
00077     return m_forename;
00078   }
00079   string_type const &surname() const
00080   {
00081     return m_surname;
00082   }
00083   unsigned          age() const
00084   {
00085     return m_age;
00086   }
00087 
00088 private:
00089   const string_type m_forename;
00090   const string_type m_surname;
00091   const unsigned    m_age;
00092 
00093 private:
00094   Person &operator =(Person const &);
00095 };
00096 
00097 /* ////////////////////////////////////////////////////////////////////////// */
00098 
00099 // Define the fe.simple process identity, so that it links when using fe.simple
00100 PANTHEIOS_EXTERN_C const char   FE_SIMPLE_PROCESS_IDENTITY[]    =   "example_cpp_custom_type_1";
00101 
00102 /* ////////////////////////////////////////////////////////////////////////// */
00103 
00104 static void log_with_explicit_conversion_code(Person const &person);
00105 static void log_with_conversion_function(Person const &person);
00106 static void log_with_string_access_shims(Person const &person);
00107 static void log_with_inserter_class(Person const &person);
00108 
00109 /* ////////////////////////////////////////////////////////////////////////// */
00110 
00111 int main()
00112 {
00113   try
00114   {
00115     Person  person(L"Dr", L"Proctor", 38);
00116 
00117     // log with explicit conversion
00118 
00119     log_with_explicit_conversion_code(person);
00120 
00121     // log with conversion function
00122 
00123     log_with_conversion_function(person);
00124 
00125     // log with string access shims
00126 
00127     log_with_string_access_shims(person);
00128 
00129     // log with inserter class
00130 
00131     log_with_inserter_class(person);
00132 
00133 
00134     return EXIT_SUCCESS;
00135   }
00136   catch(std::bad_alloc &)
00137   {
00138     pantheios::log_CRITICAL("out of memory");
00139   }
00140   catch(std::exception &x)
00141   {
00142     pantheios::log_ALERT("Exception: ", x);
00143   }
00144   catch(...)
00145   {
00146     pantheios::puts(pantheios::emergency, "Unexpected unknown error");
00147   }
00148 
00149   return EXIT_FAILURE;
00150 }
00151 
00152 /* ////////////////////////////////////////////////////////////////////////// */
00153 
00154 static void log_with_explicit_conversion_code(Person const &person)
00155 {
00156   if(pantheios::isSeverityLogged(pantheios::notice))
00157   {
00158     // Since Person's names are wide, we need to convert
00159 
00160     // NOTE: this code does not check for wcstombs() failure (returns size_t(-1))
00161 
00162     // 1. Create buffers for conversion. (auto_buffer used to minimise heap
00163     //     when not necessary.)
00164 
00165     stlsoft::auto_buffer<char>  forename(1 + ::wcstombs(NULL, person.forename().c_str(), 0));
00166     stlsoft::auto_buffer<char>  surname(1 + ::wcstombs(NULL, person.surname().c_str(), 0));
00167 
00168     // 2. Convert
00169 
00170     ::wcstombs(forename.data(), person.forename().data(), forename.size());
00171     ::wcstombs(surname.data(), person.surname().data(), surname.size());
00172 
00173     PANTHEIOS_ASSERT('\0' == forename[forename.size() - 1]);
00174     PANTHEIOS_ASSERT('\0' == surname[surname.size() - 1]);
00175 
00176     pantheios::log_NOTICE("Person: ", forename.data(), " ", surname.data(), ", aged ", pantheios::integer(person.age()));
00177   }
00178 }
00179 
00180 /* ////////////////////////////////////////////////////////////////////////// */
00181 
00182 static std::string Person_to_string(Person const &person)
00183 {
00184   // Since Person's names are wide, we need to convert
00185 
00186   // NOTE: this code does not check for wcstombs() failure (returns size_t(-1))
00187 
00188   // 1. Create buffers for conversion. (auto_buffer used to minimise heap
00189   //     when not necessary.)
00190 
00191   stlsoft::auto_buffer<char>  forename(1 + ::wcstombs(NULL, person.forename().c_str(), 0));
00192   stlsoft::auto_buffer<char>  surname(1 + ::wcstombs(NULL, person.surname().c_str(), 0));
00193 
00194   // 2. Convert
00195 
00196   ::wcstombs(forename.data(), person.forename().data(), forename.size());
00197   ::wcstombs(surname.data(), person.surname().data(), surname.size());
00198 
00199   PANTHEIOS_ASSERT('\0' == forename[forename.size() - 1]);
00200   PANTHEIOS_ASSERT('\0' == surname[surname.size() - 1]);
00201 
00202   std::string result(forename.data(), forename.size() - 1);
00203   char        sz[21];
00204 
00205   result.append(" ", 1);
00206   result.append(surname.data(), surname.size() - 1);
00207   result += ", aged ";
00208   result += stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age());
00209 
00210   return result;
00211 }
00212 
00213 static void log_with_conversion_function(Person const &person)
00214 {
00215   pantheios::log_NOTICE("Person: ", Person_to_string(person));
00216 }
00217 
00218 /* ////////////////////////////////////////////////////////////////////////// */
00219 
00220 namespace stlsoft
00221 {
00222 
00223   inline stlsoft::basic_shim_string<char, 24> c_str_data_a(Person const &person)
00224   {
00225     char          sz[21];
00226     size_t        cchNumber;
00227     char const    *num        = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age(), cchNumber);
00228     const size_t  cchForename = ::wcstombs(NULL, person.forename().data(), 0);
00229     const size_t  cchSurname  = ::wcstombs(NULL, person.surname().data(), 0);
00230     char          *p;
00231 
00232     stlsoft::basic_shim_string<char, 24>    s(person.forename().size() + 1 + person.surname().size() + 7 + cchNumber);
00233 
00234     p = s.data();
00235     p += ::wcstombs(p + 0, person.forename().data(), cchForename);
00236     p = ::strncpy(p, " ", 1) + 1;
00237     p += ::wcstombs(p, person.surname().data(), cchSurname);
00238     p = ::strncpy(p, ", aged ", 7);
00239     p = ::strncpy(p + 7, num, cchNumber);
00240     p += cchNumber;
00241     p[0] = '\0';
00242 
00243     PANTHEIOS_ASSERT(p == s.data() + s.size());
00244 
00245     return s;
00246   }
00247 
00248   inline size_t c_str_len_a(Person const &person)
00249   {
00250     char          sz[21];
00251     size_t        cchNumber;
00252     char const    *num        = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age(), cchNumber);
00253     const size_t  cchForename = ::wcstombs(NULL, person.forename().data(), 0);
00254     const size_t  cchSurname  = ::wcstombs(NULL, person.surname().data(), 0);
00255 
00256   STLSOFT_SUPPRESS_UNUSED(num);
00257 
00258     return cchForename + 1 + cchSurname + 7 + cchNumber;
00259   }
00260 
00261 } // namespace stlsoft
00262 
00263 static void log_with_string_access_shims(Person const &person)
00264 {
00265   pantheios::log_NOTICE("Person: ", person);
00266 }
00267 
00268 /* ////////////////////////////////////////////////////////////////////////// */
00269 
00270 class Person_inserter
00271 {
00272 public:
00273   typedef Person_inserter class_type;
00274 
00275 public:
00276   Person_inserter(Person const &person)
00277     : m_person(person)
00278     , m_value(0)
00279   {}
00280 
00281 #if defined(STLSOFT_COMPILER_IS_GCC)
00282   Person_inserter(class_type const &rhs)
00283     : m_person(m_person)
00284     , m_value(m_value.size())
00285   {
00286     ::memcpy(&m_value[0], &rhs.m_value[0], m_value.size());
00287   }
00288 #endif /* compiler */
00289 
00290 public:
00291   char const  *data() const
00292   {
00293     if(m_value.empty())
00294     {
00295       construct_();
00296     }
00297 
00298     return m_value.data();
00299   }
00300   size_t size() const
00301   {
00302     if(m_value.empty())
00303     {
00304       construct_();
00305     }
00306 
00307     return m_value.size();
00308   }
00309 
00310 public:
00311   void construct_() const
00312   {
00313     const_cast<class_type*>(this)->construct_();
00314   }
00315   void construct_()
00316   {
00317     char          sz[21];
00318     size_t        cchNumber;
00319     char const    *num        = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), m_person.age(), cchNumber);
00320     const size_t  cchForename = ::wcstombs(NULL, m_person.forename().data(), 0);
00321     const size_t  cchSurname  = ::wcstombs(NULL, m_person.surname().data(), 0);
00322     char          *p;
00323 
00324     m_value.resize(cchForename + 1 + cchSurname + 7 + cchNumber);
00325 
00326     p = m_value.data();
00327     p += ::wcstombs(p + 0, m_person.forename().data(), cchForename);
00328     p = ::strncpy(p, " ", 1);
00329     p += 1;
00330     p += ::wcstombs(p, m_person.surname().data(), cchSurname);
00331     p = ::strncpy(p, ", aged ", 7);
00332     p = ::strncpy(p + 7, num, cchNumber);
00333     p += cchNumber;
00334 
00335     PANTHEIOS_ASSERT(p == m_value.end());
00336   }
00337 
00338 private:
00339   Person const                    &m_person;
00340   stlsoft::auto_buffer<char, 24>  m_value;
00341 };
00342 
00343 namespace stlsoft
00344 {
00345 
00346   inline char const *c_str_data_a(Person_inserter const &pi)
00347   {
00348     return pi.data();
00349   }
00350 
00351   inline size_t c_str_len_a(Person_inserter const &pi)
00352   {
00353     return pi.size();
00354   }
00355 
00356 } // namespace stlsoft
00357 
00358 static void log_with_inserter_class(Person const &person)
00359 {
00360   pantheios::log_NOTICE("Person: ", Person_inserter(person));
00361 }
00362 
00363 /* ////////////////////////////////////////////////////////////////////////// */

pantheios Library documentation © Matthew Wilson, 2006 SourceForge.net Logo