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 |