stlsoft/error/error_desc.hpp

Go to the documentation of this file.
00001 /* /////////////////////////////////////////////////////////////////////////
00002  * File:        stlsoft/error/error_desc.hpp
00003  *
00004  * Purpose:     Converts a standard rerror code (errno) to a printable string.
00005  *
00006  * Created:     18th July 2006
00007  * Updated:     19th January 2010
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2006-2010, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * ////////////////////////////////////////////////////////////////////// */
00039 
00040 
00048 #ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_ERROR_DESC
00049 #define STLSOFT_INCL_STLSOFT_ERROR_HPP_ERROR_DESC
00050 
00051 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00052 # define STLSOFT_VER_STLSOFT_ERROR_HPP_ERROR_DESC_MAJOR     1
00053 # define STLSOFT_VER_STLSOFT_ERROR_HPP_ERROR_DESC_MINOR     0
00054 # define STLSOFT_VER_STLSOFT_ERROR_HPP_ERROR_DESC_REVISION  8
00055 # define STLSOFT_VER_STLSOFT_ERROR_HPP_ERROR_DESC_EDIT      19
00056 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00057 
00058 /* /////////////////////////////////////////////////////////////////////////
00059  * Includes
00060  */
00061 
00062 #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
00063 # include <stlsoft/stlsoft.h>
00064 #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
00065 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
00066 # include <stlsoft/memory/allocator_selector.hpp>
00067 #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
00068 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
00069 # include <stlsoft/memory/auto_buffer.hpp>
00070 #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
00071 #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CSTRING_FUNCTIONS
00072 # include <stlsoft/string/cstring_functions.hpp>
00073 #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CSTRING_FUNCTIONS */
00074 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_STRING_H_FWD
00075 # include <stlsoft/shims/access/string/fwd.h>
00076 #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_STRING_H_FWD */
00077 #ifndef STLSOFT_INCL_STLSOFT_INTERNAL_H_SAFESTR
00078 # include <stlsoft/internal/safestr.h>
00079 #endif /* !STLSOFT_INCL_STLSOFT_INTERNAL_H_SAFESTR */
00080 
00081 #ifndef STLSOFT_INCL_H_STRING
00082 # define STLSOFT_INCL_H_STRING
00083 # include <string.h>                    // for strerror()
00084 #endif /* !STLSOFT_INCL_H_STRING */
00085 
00086 #ifdef STLSOFT_UNITTEST
00087 # include <errno.h>
00088 #endif /* STLSOFT_UNITTEST */
00089 
00090 /* /////////////////////////////////////////////////////////////////////////
00091  * Compatibility
00092  */
00093 
00094 #if (   defined(STLSOFT_COMPILER_IS_MSVC) || \
00095         defined(STLSOFT_COMPILER_IS_INTEL)) && \
00096     _MSC_VER >= 1300
00097 # define STLSOFT_ERROR_DESC_wcserror    ::_wcserror
00098 #endif /* compiler */
00099 
00100 #if (   defined(STLSOFT_COMPILER_IS_MSVC) || \
00101         defined(STLSOFT_COMPILER_IS_INTEL)) && \
00102     _MSC_VER >= 1400
00103 # define STLSOFT_ERROR_DESC_wcserror_s  ::_wcserror_s
00104 #endif /* compiler */
00105 
00106 #ifdef STLSOFT_USING_SAFE_STR_FUNCTIONS
00107 # ifdef STLSOFT_ERROR_DESC_wcserror_s
00108 #  define STLSOFT_ERROR_DESC_WIDE_STRING_SUPPORT_
00109 # endif /* STLSOFT_ERROR_DESC_wcserror_s */
00110 #else /* ? STLSOFT_USING_SAFE_STR_FUNCTIONS */
00111 # ifdef STLSOFT_ERROR_DESC_wcserror
00112 #  define STLSOFT_ERROR_DESC_WIDE_STRING_SUPPORT_
00113 # endif /* STLSOFT_ERROR_DESC_wcserror */
00114 #endif /* STLSOFT_USING_SAFE_STR_FUNCTIONS */
00115 
00116 /* /////////////////////////////////////////////////////////////////////////
00117  * Namespace
00118  */
00119 
00120 #ifndef _STLSOFT_NO_NAMESPACE
00121 namespace stlsoft
00122 {
00123 #endif /* !_STLSOFT_NO_NAMESPACE */
00124 
00125 /* /////////////////////////////////////////////////////////////////////////
00126  * Helpers
00127  */
00128 
00129 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00130 
00131 template <ss_typename_param_k C>
00132 struct error_desc_traits;
00133 
00134 STLSOFT_TEMPLATE_SPECIALISATION
00135 struct error_desc_traits<ss_char_a_t>
00136 {
00137 # ifdef STLSOFT_USING_SAFE_STR_FUNCTIONS
00138 
00139     static int invoke_strerror_s_(ss_char_a_t* buff, size_t n, int code)
00140     {
00141         return ::strerror_s(buff, n, code);
00142     }
00143 
00144 # else /* ? STLSOFT_USING_SAFE_STR_FUNCTIONS */
00145 
00146     static ss_char_a_t const* invoke_strerror_(int code, ss_char_a_t const*)
00147     {
00148         return ::strerror(code);
00149     }
00150 
00151 # endif /* STLSOFT_USING_SAFE_STR_FUNCTIONS */
00152 };
00153 
00154 # ifdef STLSOFT_USING_SAFE_STR_FUNCTIONS
00155 
00156 #  ifdef STLSOFT_ERROR_DESC_wcserror_s
00157 
00158 STLSOFT_TEMPLATE_SPECIALISATION
00159 struct error_desc_traits<ss_char_w_t>
00160 {
00161     static int invoke_strerror_s_(ss_char_w_t* buff, size_t n, int code)
00162     {
00163         return STLSOFT_ERROR_DESC_wcserror_s(buff, n, code);
00164     }
00165 };
00166 
00167 #  else /* ? STLSOFT_ERROR_DESC_wcserror_s */
00168 
00169 STLSOFT_TEMPLATE_SPECIALISATION
00170 struct error_desc_traits<ss_char_a_t>;
00171 
00172 #  endif /* STLSOFT_ERROR_DESC_wcserror_s */
00173 
00174 # else /* ? STLSOFT_USING_SAFE_STR_FUNCTIONS */
00175 
00176 #  ifdef STLSOFT_ERROR_DESC_wcserror
00177 
00178 STLSOFT_TEMPLATE_SPECIALISATION
00179 struct error_desc_traits<ss_char_w_t>
00180 {
00181     static ss_char_w_t const* invoke_strerror_(int code, ss_char_w_t const*)
00182     {
00183         return STLSOFT_ERROR_DESC_wcserror(code);
00184     }
00185 };
00186 
00187 #  else /* ? STLSOFT_ERROR_DESC_wcserror_s */
00188 
00189 STLSOFT_TEMPLATE_SPECIALISATION
00190 struct error_desc_traits<ss_char_w_t>;
00191 
00192 #  endif /* STLSOFT_ERROR_DESC_wcserror */
00193 
00194 # endif /* STLSOFT_USING_SAFE_STR_FUNCTIONS */
00195 
00196 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00197 
00198 /* /////////////////////////////////////////////////////////////////////////
00199  * Classes
00200  */
00201 
00234 template <ss_typename_param_k C>
00235 class basic_error_desc
00236 #if defined(STLSOFT_COMPILER_IS_DMC)
00237     : protected allocator_selector<C>::allocator_type
00238 #else /* ? compiler */
00239     : private allocator_selector<C>::allocator_type
00240 #endif /* compiler */
00241 {
00244 private:
00245     typedef ss_typename_type_k allocator_selector<C>::allocator_type    parent_class_type;
00246     typedef ss_typename_type_k allocator_selector<C>::allocator_type    allocator_type;
00247 public:
00249     typedef C                                                           char_type;
00251     typedef basic_error_desc<C>                                         class_type;
00253     typedef int                                                         error_type;
00255     typedef ss_size_t                                                   size_type;
00256 private:
00257     typedef error_desc_traits<char_type>                                traits_type;
00259 
00262 public:
00266     ss_explicit_k basic_error_desc(error_type error = errno);
00268     ~basic_error_desc() stlsoft_throw_0();
00270 
00273 public:
00275     char_type const* get_description() const stlsoft_throw_0();
00277 
00280 public:
00282     char_type const*    c_str() const stlsoft_throw_0();
00284     size_type           length() const stlsoft_throw_0();
00286     size_type           size() const stlsoft_throw_0();
00288 
00291 private:
00292     allocator_type& get_allocator_();
00294 
00297 private:
00298     char_type*  m_str;
00299     size_type   m_length;
00301 
00304 private:
00305     basic_error_desc(class_type const&);
00306     basic_error_desc& operator =(class_type const&);
00308 };
00309 
00310 /* Typedefs to commonly encountered types. */
00315 typedef basic_error_desc<ss_char_a_t>   error_desc_a;
00320 typedef basic_error_desc<ss_char_w_t>   error_desc_w;
00325 typedef basic_error_desc<char>          error_desc;
00326 
00327 /* /////////////////////////////////////////////////////////////////////////
00328  * Implementation
00329  */
00330 
00331 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00332 
00333 template <ss_typename_param_k C>
00334 inline ss_typename_type_ret_k basic_error_desc<C>::allocator_type &basic_error_desc<C>::get_allocator_()
00335 {
00336     return *this;
00337 }
00338 
00339 template <ss_typename_param_k C>
00340 inline basic_error_desc<C>::basic_error_desc(ss_typename_type_k basic_error_desc<C>::error_type error /* = errno */)
00341 #ifdef STLSOFT_USING_SAFE_STR_FUNCTIONS
00342     : m_length(0)
00343 {
00344     stlsoft::auto_buffer<char_type, 128, allocator_type>    buff(128);
00345 
00346     for(;;)
00347     {
00348         // If you get compiler errors on the following line, it may be because
00349         // you are trying to use a wide char specialisation of basic_error_desc
00350         // with a compiler for which a definition for
00351         // STLSOFT_ERROR_DESC_wcserror_s does not exist. If your platform has an
00352         // equivalental function, as does Microsoft's with _wcserror_s(), then
00353         // define STLSOFT_ERROR_DESC_wcserror_s to the name of your function
00354         int n = traits_type::invoke_strerror_s_(&buff[0], buff.size() - 1, error);
00355 
00356         buff[buff.size() - 1u] = '\0';
00357 
00358         if(0 == n)
00359         {
00360             size_t cch = c_str_len(buff.data());
00361 
00362             if(cch < buff.size() - 2u)
00363             {
00364                 m_length = cch;
00365                 buff.resize(cch + 1u);
00366                 break;
00367             }
00368         }
00369 
00370         if(!buff.resize(1u + buff.size() * 2u))
00371         {
00372             buff.resize(1u);
00373             break;
00374         }
00375     }
00376 
00377     m_str = string_dup(buff.data(), m_length, get_allocator_());
00378 }
00379 #else /* ? STLSOFT_USING_SAFE_STR_FUNCTIONS */
00380     // If you get compiler errors on the following line, it may be because
00381     // you are trying to use a wide char specialisation of basic_error_desc
00382     // with a compiler for which a definition for
00383     // STLSOFT_ERROR_DESC_wcserror does not exist. If your platform has an
00384     // equivalental function, as does Microsoft's with _wcserror(), then
00385     // define STLSOFT_ERROR_DESC_wcserror to the name of your function
00386     : m_str(string_dup(traits_type::invoke_strerror_(error, static_cast<char_type const*>(0)), get_allocator_(), &m_length))
00387 {}
00388 #endif /* STLSOFT_USING_SAFE_STR_FUNCTIONS */
00389 
00390 template <ss_typename_param_k C>
00391 inline basic_error_desc<C>::~basic_error_desc() stlsoft_throw_0()
00392 {
00393     get_allocator_().deallocate(m_str, m_length);
00394 }
00395 
00396 template <ss_typename_param_k C>
00397 inline ss_typename_type_ret_k basic_error_desc<C>::char_type const* basic_error_desc<C>::get_description() const stlsoft_throw_0()
00398 {
00399     static const char_type s_nullMessage[1] = { '\0' };
00400 
00401     return (NULL != m_str) ? m_str : s_nullMessage;
00402 }
00403 
00404 template <ss_typename_param_k C>
00405 inline ss_typename_type_ret_k basic_error_desc<C>::char_type const* basic_error_desc<C>::c_str() const stlsoft_throw_0()
00406 {
00407     return get_description();
00408 }
00409 
00410 template <ss_typename_param_k C>
00411 inline ss_typename_type_ret_k basic_error_desc<C>::size_type basic_error_desc<C>::length() const stlsoft_throw_0()
00412 {
00413     return m_length;
00414 }
00415 
00416 template <ss_typename_param_k C>
00417 inline ss_typename_type_ret_k basic_error_desc<C>::size_type basic_error_desc<C>::size() const stlsoft_throw_0()
00418 {
00419     return length();
00420 }
00421 
00422 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00423 
00424 /* /////////////////////////////////////////////////////////////////////////
00425  * String access shims
00426  */
00427 
00428 #ifndef STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED
00429 
00434 template <ss_typename_param_k C>
00435 inline C const* c_str_ptr_null(stlsoft_ns_qual(basic_error_desc)<C> const& e)
00436 {
00437     return (0 != e.length()) ? e.c_str() : NULL;
00438 }
00439 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00440 inline ss_char_a_t const* c_str_ptr_null_a(stlsoft_ns_qual(basic_error_desc)<ss_char_a_t> const& e)
00441 {
00442     return (0 != e.length()) ? e.c_str() : NULL;
00443 }
00444 inline ss_char_w_t const* c_str_ptr_null_w(stlsoft_ns_qual(basic_error_desc)<ss_char_w_t> const& e)
00445 {
00446     return (0 != e.length()) ? e.c_str() : NULL;
00447 }
00448 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00449 
00454 template <ss_typename_param_k C>
00455 inline C const* c_str_ptr(stlsoft_ns_qual(basic_error_desc)<C> const& e)
00456 {
00457     return e.c_str();
00458 }
00459 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00460 inline ss_char_a_t const* c_str_ptr_a(stlsoft_ns_qual(basic_error_desc)<ss_char_a_t> const& e)
00461 {
00462     return e.c_str();
00463 }
00464 inline ss_char_w_t const* c_str_ptr_w(stlsoft_ns_qual(basic_error_desc)<ss_char_w_t> const& e)
00465 {
00466     return e.c_str();
00467 }
00468 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00469 
00474 template <ss_typename_param_k C>
00475 inline C const* c_str_data(stlsoft_ns_qual(basic_error_desc)<C> const& e)
00476 {
00477     return e.c_str();
00478 }
00479 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00480 inline ss_char_a_t const* c_str_data_a(stlsoft_ns_qual(basic_error_desc)<ss_char_a_t> const& e)
00481 {
00482     return e.c_str();
00483 }
00484 inline ss_char_w_t const* c_str_data_w(stlsoft_ns_qual(basic_error_desc)<ss_char_w_t> const& e)
00485 {
00486     return e.c_str();
00487 }
00488 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00489 
00494 template <ss_typename_param_k C>
00495 inline ss_size_t c_str_len(stlsoft_ns_qual(basic_error_desc)<C> const& e)
00496 {
00497     return e.length();
00498 }
00499 
00500 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00501 inline ss_size_t c_str_len_a(stlsoft_ns_qual(basic_error_desc)<ss_char_a_t> const& e)
00502 {
00503     return e.length();
00504 }
00505 inline ss_size_t c_str_len_w(stlsoft_ns_qual(basic_error_desc)<ss_char_w_t> const& e)
00506 {
00507     return e.length();
00508 }
00509 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00510 
00511 
00516 template <ss_typename_param_k C>
00517 inline C const* get_ptr(stlsoft_ns_qual(basic_error_desc)<C> const& e)
00518 {
00519     return e;
00520 }
00521 
00522 
00527 template<   ss_typename_param_k S
00528         ,   ss_typename_param_k C
00529         >
00530 inline S& operator <<(S& s, stlsoft_ns_qual(basic_error_desc)<C> const& e)
00531 {
00532     s << e.get_description();
00533 
00534     return s;
00535 }
00536 
00537 #endif /* !STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED */
00538 
00540 // Unit-testing
00541 
00542 #ifdef STLSOFT_UNITTEST
00543 # include "./unittest/error_desc_unittest_.h"
00544 #endif /* STLSOFT_UNITTEST */
00545 
00546 /* ////////////////////////////////////////////////////////////////////// */
00547 
00548 #ifndef _STLSOFT_NO_NAMESPACE
00549 } // namespace stlsoft
00550 #endif /* _STLSOFT_NO_NAMESPACE */
00551 
00552 /* /////////////////////////////////////////////////////////////////////////
00553  * Global namespace shims
00554  */
00555 
00556 /* This defines stream inserter shim function templates for the converters
00557  * for use with the Visual C++ <7.1 standard library.
00558  */
00559 
00560 #if defined(STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC) && \
00561     STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION < STLSOFT_CF_DINKUMWARE_VC_VERSION_7_1
00562 
00563 # include <iosfwd>
00564 
00565 #if 0
00566 template <ss_typename_param_k C>
00567 inline stlsoft_ns_qual_std(basic_ostream)<C>& operator <<(stlsoft_ns_qual_std(basic_ostream)<C> &stm, stlsoft_ns_qual(basic_error_desc)<C> const& desc)
00568 {
00569     return stm << desc.c_str();
00570 }
00571 #endif /* 0 */
00572 
00573 #endif /* library */
00574 
00575 /* ////////////////////////////////////////////////////////////////////// */
00576 
00577 #endif /* !STLSOFT_INCL_STLSOFT_ERROR_HPP_ERROR_DESC */
00578 
00579 /* ///////////////////////////// end of file //////////////////////////// */

Generated on Fri Mar 5 06:31:01 2010 for STLSoft by  doxygen 1.5.4