blocxx

SafeCString.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2006, Novell, Inc. All rights reserved.
00004 * 
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 * 
00008 *     * Redistributions of source code must retain the above copyright notice,
00009 *       this list of conditions and the following disclaimer.
00010 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of 
00014 *       Vintela, Inc., 
00015 *       nor Novell, Inc., 
00016 *       nor the names of its contributors or employees may be used to 
00017 *       endorse or promote products derived from this software without 
00018 *       specific prior written permission.
00019 * 
00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030 * POSSIBILITY OF SUCH DAMAGE.
00031 *******************************************************************************/
00032 
00033 
00038 #ifndef BLOCXX_SAFE_CSTRING_HPP_INCLUDE_GUARD_
00039 #define BLOCXX_SAFE_CSTRING_HPP_INCLUDE_GUARD_
00040 
00041 #include "blocxx/BLOCXX_config.h"
00042 #include <cstddef>
00043 #include <cstdarg>
00044 #include <cstdio>  // for vsnprintf
00045 #include "blocxx/Exception.hpp"
00046 
00047 
00048 namespace BLOCXX_NAMESPACE
00049 {
00050 
00051 namespace SafeCString
00052 {
00053 #ifdef BLOCXX_WIN32
00054 #define vsnprintf _vsnprintf
00055 #endif
00056 
00060    BLOCXX_COMMON_API char * str_dup(char const * s);
00061 
00066    char * str_dup_nothrow(char const * s);
00067 
00068 
00074    inline char const * nonull(char const * s)
00075    {
00076       return s ? s : "";
00077    }
00078 
00079 
00095    char * strcpy_trunc(char * dst, std::size_t dstsize, char const * src);
00096 
00112    char * strcpy_trunc(
00113       char * dst, std::size_t dstsize, char const * src, std::size_t srclen
00114    );
00115 
00119    template <std::size_t N> inline
00120    char * strcpy_trunc(char (&dst)[N], char const * src)
00121    {
00122       return strcpy_trunc(dst, N, src);
00123    }
00124 
00128    template <std::size_t N> inline
00129    char * strcpy_trunc(char (&dst)[N], char const * src, std::size_t srclen)
00130    {
00131       return strcpy_trunc(dst, N, src, srclen);
00132    }
00133 
00138    template <std::size_t N> inline
00139    std::size_t strcpy_to_pos_trunc(
00140       char (&dst)[N], std::size_t pos, char const * src
00141    )
00142    {
00143       return strcpy_trunc(dst + pos, N - pos, src) - dst;
00144    }
00145 
00150    template <std::size_t N> inline
00151    std::size_t strcpy_to_pos_trunc(
00152       char (&dst)[N], std::size_t pos, char const * src, std::size_t srclen
00153    )
00154    {
00155       return strcpy_trunc(dst + pos, N - pos, src, srclen) - dst;
00156    }
00157 
00158    BLOCXX_DECLARE_EXCEPTION(Overflow);
00160    int const RESULT_TRUNCATED = 0;
00161    int const DEST_UNTERMINATED = 1;
00162 
00180    char * strcpy_check(char * dst, std::size_t dstsize, char const * src);
00181 
00199    char * strcpy_check(
00200       char * dst, std::size_t dstsize, char const * src, std::size_t srclen
00201    );
00202 
00206    template <std::size_t N> inline
00207    char * strcpy_check(char (&dst)[N], char const * src)
00208    {
00209       return strcpy_check(dst, N, src);
00210    }
00211 
00215    template <std::size_t N> inline
00216    char * strcpy_check(char (&dst)[N], char const * src, std::size_t srclen)
00217    {
00218       return strcpy_check(dst, N, src, srclen);
00219    }
00220 
00225    template <std::size_t N> inline
00226    std::size_t strcpy_to_pos_check(
00227       char (&dst)[N], std::size_t pos, char const * src
00228    )
00229    {
00230       return strcpy_check(dst + pos, N - pos, src) - dst;
00231    }
00232 
00237    template <std::size_t N> inline
00238    std::size_t strcpy_to_pos_check(
00239       char (&dst)[N], std::size_t pos, char const * src, std::size_t srclen
00240    )
00241    {
00242       return strcpy_check(dst + pos, N - pos, src, srclen) - dst;
00243    }
00244 
00245 
00263    char * strcat_trunc(char * dst, std::size_t dstsize, char const * src);
00264 
00283    char * strcat_trunc(
00284       char * dst, std::size_t dstsize, char const * src, std::size_t srclen
00285    );
00286 
00290    template <std::size_t N> inline
00291    char * strcat_trunc(char (&dst)[N], char const * src)
00292    {
00293       return strcat_trunc(dst, N, src);
00294    }
00295 
00299    template <std::size_t N> inline
00300    char * strcat_trunc(char (&dst)[N], char const * src, std::size_t srclen)
00301    {
00302       return strcat_trunc(dst, N, src, srclen);
00303    }
00304 
00326    char * strcat_check(char * dst, std::size_t dstsize, char const * src);
00327 
00350    char * strcat_check(
00351       char * dst, std::size_t dstsize, char const * src, std::size_t srclen
00352    );
00353 
00357    template <std::size_t N> inline
00358    char * strcat_check(char (&dst)[N], char const * src)
00359    {
00360       return strcat_check(dst, N, src);
00361    }
00362 
00366    template <std::size_t N> inline
00367    char * strcat_check(char (&dst)[N], char const * src, std::size_t srclen)
00368    {
00369       return strcat_check(dst, N, src, srclen);
00370    }
00371 
00372 
00373    namespace Impl
00374    {
00375       inline std::size_t nchars_output(int retval, std::size_t dstsize)
00376       {
00377          return (
00378             retval < 0 || retval >= static_cast<int>(dstsize) ?   dstsize - 1
00379             : static_cast<std::size_t>(retval)
00380          );
00381       }
00382       
00383       std::size_t nchars_check(int retval, std::size_t dstsize);
00384    }
00385 
00392    template <typename T1>
00393    std::size_t sprintf_trunc(
00394       char * dst, std::size_t dstsize, char const * fmt, T1 const & x1
00395    )
00396    {
00397       return Impl::nchars_output(snprintf(dst, dstsize, fmt, x1), dstsize);
00398    }
00399 
00406    template <typename T1, typename T2>
00407    std::size_t sprintf_trunc(
00408       char * dst, std::size_t dstsize, char const * fmt,
00409       T1 const & x1, T2 const & x2
00410    )
00411    {
00412       return Impl::nchars_output(
00413          snprintf(dst, dstsize, fmt, x1, x2), dstsize);
00414    }
00415 
00422    template <typename T1, typename T2, typename T3>
00423    std::size_t sprintf_trunc(
00424       char * dst, std::size_t dstsize, char const * fmt,
00425       T1 const & x1, T2 const & x2, T3 const & x3
00426    )
00427    {
00428       return Impl::nchars_output(
00429          snprintf(dst, dstsize, fmt, x1, x2, x3), dstsize);
00430    }
00431 
00438    template <typename T1, typename T2, typename T3, typename T4>
00439    std::size_t sprintf_trunc(
00440       char * dst, std::size_t dstsize, char const * fmt,
00441       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
00442    )
00443    {
00444       return Impl::nchars_output(
00445          snprintf(dst, dstsize, fmt, x1, x2, x3, x4), dstsize);
00446    }
00447 
00454    template <typename T1, typename T2, typename T3, typename T4, typename T5>
00455    std::size_t sprintf_trunc(
00456       char * dst, std::size_t dstsize, char const * fmt,
00457       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
00458    )
00459    {
00460       return Impl::nchars_output(
00461          snprintf(dst, dstsize, fmt, x1, x2, x3, x4, x5), dstsize);
00462    }
00463 
00467    template <std::size_t N, typename T1>
00468    std::size_t sprintf_trunc(char (&dst)[N], char const * fmt, T1 const & x1)
00469    {
00470       return Impl::nchars_output(snprintf(dst, N, fmt, x1), N);
00471    }
00472 
00476    template <std::size_t N, typename T1, typename T2>
00477    std::size_t sprintf_trunc(
00478       char (&dst)[N], char const * fmt, T1 const & x1, T2 const & x2
00479    )
00480    {
00481       return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2), N);
00482    }
00483 
00487    template <std::size_t N, typename T1, typename T2, typename T3>
00488    std::size_t sprintf_trunc(
00489       char (&dst)[N], char const * fmt,
00490       T1 const & x1, T2 const & x2, T3 const & x3
00491    )
00492    {
00493       return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2, x3), N);
00494    }
00495 
00499    template <std::size_t N, typename T1, typename T2, typename T3, typename T4>
00500    std::size_t sprintf_trunc(
00501       char (&dst)[N], char const * fmt,
00502       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
00503    )
00504    {
00505       return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2, x3, x4), N);
00506    }
00507 
00511    template <std::size_t N, typename T1, typename T2, typename T3, typename T4,
00512            typename T5>
00513    std::size_t sprintf_trunc(
00514       char (&dst)[N], char const * fmt,
00515       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
00516    )
00517    {
00518       return Impl::nchars_output(
00519          snprintf(dst, N, fmt, x1, x2, x3, x4, x5), N);
00520    }
00521 
00522 
00531    template <typename T1>
00532    std::size_t sprintf_check(
00533       char * dst, std::size_t dstsize, char const * fmt, T1 const & x1
00534    )
00535    {
00536       return Impl::nchars_check(snprintf(dst, dstsize, fmt, x1), dstsize);
00537    }
00538 
00547    template <typename T1, typename T2>
00548    std::size_t sprintf_check(
00549       char * dst, std::size_t dstsize, char const * fmt,
00550       T1 const & x1, T2 const & x2
00551    )
00552    {
00553       return Impl::nchars_check(
00554          snprintf(dst, dstsize, fmt, x1, x2), dstsize);
00555    }
00556 
00565    template <typename T1, typename T2, typename T3>
00566    std::size_t sprintf_check(
00567       char * dst, std::size_t dstsize, char const * fmt,
00568       T1 const & x1, T2 const & x2, T3 const & x3
00569    )
00570    {
00571       return Impl::nchars_check(
00572          snprintf(dst, dstsize, fmt, x1, x2, x3), dstsize);
00573    }
00574 
00583    template <typename T1, typename T2, typename T3, typename T4>
00584    std::size_t sprintf_check(
00585       char * dst, std::size_t dstsize, char const * fmt,
00586       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
00587    )
00588    {
00589       return Impl::nchars_check(
00590          snprintf(dst, dstsize, fmt, x1, x2, x3, x4), dstsize);
00591    }
00592 
00601    template <typename T1, typename T2, typename T3, typename T4, typename T5>
00602    std::size_t sprintf_check(
00603       char * dst, std::size_t dstsize, char const * fmt,
00604       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
00605    )
00606    {
00607       return Impl::nchars_check(
00608          snprintf(dst, dstsize, fmt, x1, x2, x3, x4, x5), dstsize);
00609    }
00610 
00614    template <std::size_t N, typename T1>
00615    std::size_t sprintf_check(char (&dst)[N], char const * fmt, T1 const & x1)
00616    {
00617       return Impl::nchars_check(snprintf(dst, N, fmt, x1), N);
00618    }
00619 
00623    template <std::size_t N, typename T1, typename T2>
00624    std::size_t sprintf_check(
00625       char (&dst)[N], char const * fmt, T1 const & x1, T2 const & x2
00626    )
00627    {
00628       return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2), N);
00629    }
00630 
00634    template <std::size_t N, typename T1, typename T2, typename T3>
00635    std::size_t sprintf_check(
00636       char (&dst)[N], char const * fmt,
00637       T1 const & x1, T2 const & x2, T3 const & x3
00638    )
00639    {
00640       return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3), N);
00641    }
00642 
00646    template <std::size_t N, typename T1, typename T2, typename T3, typename T4>
00647    std::size_t sprintf_check(
00648       char (&dst)[N], char const * fmt,
00649       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
00650    )
00651    {
00652       return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3, x4), N);
00653    }
00654 
00658    template <std::size_t N, typename T1, typename T2, typename T3, typename T4,
00659            typename T5>
00660    std::size_t sprintf_check(
00661       char (&dst)[N], char const * fmt,
00662       T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
00663    )
00664    {
00665       return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3, x4, x5), N);
00666    }
00667 
00668 
00675    template <typename T1>
00676    std::size_t vprintf_trunc(
00677       char * dst, std::size_t dstsize, char const * fmt, va_list ap
00678    )
00679    {
00680       return Impl::nchars_output(vsnprintf(dst, dstsize, fmt, ap), dstsize);
00681    }
00682 
00686    template <std::size_t N> inline
00687    std::size_t vprintf_trunc(char (&dst)[N], char const * fmt, va_list ap)
00688    {
00689       return vprintf_trunc(dst, N, fmt, ap);
00690    }
00691 
00692 
00701    inline std::size_t vprintf_check(
00702       char * dst, std::size_t dstsize, char const * fmt, va_list ap
00703    )
00704    {
00705       return Impl::nchars_check(vsnprintf(dst, dstsize, fmt, ap), dstsize);
00706    }
00707 
00711    template <std::size_t N> inline
00712    std::size_t vprintf_check(char (&dst)[N], char const * fmt, va_list ap)
00713    {
00714       return vprintf_check(dst, N, fmt, ap);
00715    }
00716 
00717 } // namespace SafeCString
00718 } // namespace BLOCXX_NAMESPACE
00719 
00720 #define BLOCXX_INTSTR_AUX(x) # x
00721    /*
00722     * Use the BLOCXX_INTSTR macro to insert symbolic constants into format strings.
00723     * A typical usage would be for a maximum field width when using the
00724     * scanf family of functions.  For example, suppose that buf is an array of
00725     * STRMAX + 1 characters, and STRMAX is a manifest constant.  Then one
00726     * might write
00727     *
00728     *   sscanf(inpstr, "Name: %." BLOCXX_INTSTR(STRMAX) "s\n", buf);
00729    */
00730 #define BLOCXX_INTSTR(x) BLOCXX_INTSTR_AUX(x)
00731 
00732 #endif