#include <stlsoft/stlsoft.h>
#include <platformstl/platformstl.h>
#if defined(STLSOFT_COMPILER_IS_GCC) && \
( !defined(UNIXSTL_OS_IS_MACOSX) || \
__GNUC__ < 4)
# include <stlsoft/string/shim_string.hpp>
class Person;
class Person_inserter;
namespace stlsoft
{
char const *c_str_data_a(Person_inserter const& pi);
size_t c_str_len_a(Person_inserter const& pi);
stlsoft::basic_shim_string<char> c_str_data_a(Person const& person);
size_t c_str_len_a(Person const& pi);
}
#endif
#include <pantheios/pantheios.hpp>
#include <pantheios/inserters/integer.hpp>
#include <pantheios/quality/contract.h>
#include <stlsoft/conversion/integer_to_string.hpp>
#include <pantheios/util/memory/auto_buffer_selector.hpp>
#include <stlsoft/string/shim_string.hpp>
#include <exception>
#include <new>
#include <string>
#include <stdlib.h>
class Person
{
private:
typedef std::wstring string_type;
public:
Person(wchar_t const *forename, wchar_t const *surname, unsigned age)
: m_forename(forename)
, m_surname(surname)
, m_age(age)
{}
public:
string_type const& forename() const
{
return m_forename;
}
string_type const& surname() const
{
return m_surname;
}
unsigned age() const
{
return m_age;
}
private:
const string_type m_forename;
const string_type m_surname;
const unsigned m_age;
private:
Person &operator =(Person const&);
};
PANTHEIOS_EXTERN_C const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "example.cpp.custom_type_1";
static void log_with_explicit_conversion_code(Person const& person);
static void log_with_conversion_function(Person const& person);
static void log_with_string_access_shims(Person const& person);
static void log_with_inserter_class(Person const& person);
int main()
{
try
{
Person person(L"Dr", L"Proctor", 38);
log_with_explicit_conversion_code(person);
log_with_conversion_function(person);
log_with_string_access_shims(person);
log_with_inserter_class(person);
return EXIT_SUCCESS;
}
catch(std::bad_alloc&)
{
pantheios::log_ALERT("out of memory");
}
catch(std::exception& x)
{
pantheios::log_CRITICAL("Exception: ", x);
}
catch(...)
{
pantheios::logputs(pantheios::emergency, "Unexpected unknown error");
}
return EXIT_FAILURE;
}
static void log_with_explicit_conversion_code(Person const& person)
{
if(pantheios::isSeverityLogged(pantheios::notice))
{
typedef pantheios::util::auto_buffer_selector<char, 256>::type buffer_t;
buffer_t forename(1 + ::wcstombs(NULL, person.forename().c_str(), 0));
buffer_t surname(1 + ::wcstombs(NULL, person.surname().c_str(), 0));
::wcstombs(forename.data(), person.forename().data(), forename.size());
::wcstombs(surname.data(), person.surname().data(), surname.size());
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("the forename was incorrectly converted", '\0' == forename[forename.size() - 1]);
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("the surname was incorrectly converted", '\0' == surname[surname.size() - 1]);
pantheios::log_NOTICE("Person: ", forename.data(), " ", surname.data(), ", aged ", pantheios::integer(person.age()));
}
}
static std::string Person_to_string(Person const& person)
{
typedef pantheios::util::auto_buffer_selector<char, 256>::type buffer_t;
buffer_t forename(1 + ::wcstombs(NULL, person.forename().c_str(), 0));
buffer_t surname(1 + ::wcstombs(NULL, person.surname().c_str(), 0));
::wcstombs(forename.data(), person.forename().data(), forename.size());
::wcstombs(surname.data(), person.surname().data(), surname.size());
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("the forename was incorrectly converted", '\0' == forename[forename.size() - 1]);
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("the surname was incorrectly converted", '\0' == surname[surname.size() - 1]);
std::string result(forename.data(), forename.size() - 1);
char sz[21];
result.append(" ", 1);
result.append(surname.data(), surname.size() - 1);
result += ", aged ";
result += stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age());
return result;
}
static void log_with_conversion_function(Person const& person)
{
pantheios::log_NOTICE("Person: ", Person_to_string(person));
}
namespace stlsoft
{
inline stlsoft::basic_shim_string<char> c_str_data_a(Person const& person)
{
char sz[21];
size_t cchNumber;
char const *num = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age(), cchNumber);
const size_t cchForename = ::wcstombs(NULL, person.forename().data(), 0);
const size_t cchSurname = ::wcstombs(NULL, person.surname().data(), 0);
char *p;
stlsoft::basic_shim_string<char> s(person.forename().size() + 1 + person.surname().size() + 7 + cchNumber);
p = s.data();
p += ::wcstombs(p + 0, person.forename().data(), cchForename);
p = ::strncpy(p, " ", 1) + 1;
p += ::wcstombs(p, person.surname().data(), cchSurname);
p = ::strncpy(p, ", aged ", 7);
p = ::strncpy(p + 7, num, cchNumber);
p += cchNumber;
p[0] = '\0';
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("incorrect number of characters written", p == s.data() + s.size());
return s;
}
inline size_t c_str_len_a(Person const& person)
{
char sz[21];
size_t cchNumber;
char const *num = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), person.age(), cchNumber);
const size_t cchForename = ::wcstombs(NULL, person.forename().data(), 0);
const size_t cchSurname = ::wcstombs(NULL, person.surname().data(), 0);
STLSOFT_SUPPRESS_UNUSED(num);
return cchForename + 1 + cchSurname + 7 + cchNumber;
}
}
static void log_with_string_access_shims(Person const& person)
{
pantheios::log_NOTICE("Person: ", person);
}
class Person_inserter
{
public:
typedef Person_inserter class_type;
public:
Person_inserter(Person const& person)
: m_person(person)
, m_value(0)
{}
#if defined(STLSOFT_COMPILER_IS_GCC)
Person_inserter(class_type const& rhs)
: m_person(m_person)
, m_value(m_value.size())
{
::memcpy(&m_value[0], &rhs.m_value[0], m_value.size());
}
#endif
public:
char const *data() const
{
if(m_value.empty())
{
construct_();
}
return m_value.data();
}
size_t size() const
{
if(m_value.empty())
{
construct_();
}
return m_value.size();
}
public:
void construct_() const
{
const_cast<class_type*>(this)->construct_();
}
void construct_()
{
char sz[21];
size_t cchNumber;
char const *num = stlsoft::integer_to_string(sz, STLSOFT_NUM_ELEMENTS(sz), m_person.age(), cchNumber);
const size_t cchForename = ::wcstombs(NULL, m_person.forename().data(), 0);
const size_t cchSurname = ::wcstombs(NULL, m_person.surname().data(), 0);
char *p;
m_value.resize(cchForename + 1 + cchSurname + 7 + cchNumber);
p = m_value.data();
p += ::wcstombs(p + 0, m_person.forename().data(), cchForename);
p = ::strncpy(p, " ", 1);
p += 1;
p += ::wcstombs(p, m_person.surname().data(), cchSurname);
p = ::strncpy(p, ", aged ", 7);
p = ::strncpy(p + 7, num, cchNumber);
p += cchNumber;
PANTHEIOS_CONTRACT_ENFORCE_POSTCONDITION_RETVAL("incorrect number of characters written", p == &*m_value.end());
}
private:
typedef pantheios::util::auto_buffer_selector<char, 256>::type buffer_type;
Person const &m_person;
buffer_type m_value;
};
namespace stlsoft
{
inline char const *c_str_data_a(Person_inserter const& pi)
{
return pi.data();
}
inline size_t c_str_len_a(Person_inserter const& pi)
{
return pi.size();
}
}
static void log_with_inserter_class(Person const& person)
{
pantheios::log_NOTICE("Person: ", Person_inserter(person));
}