blocxx
|
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