blocxx
SafeCString.hpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
37
38#ifndef BLOCXX_SAFE_CSTRING_HPP_INCLUDE_GUARD_
39#define BLOCXX_SAFE_CSTRING_HPP_INCLUDE_GUARD_
40
41#include "blocxx/BLOCXX_config.h"
42#include <cstddef>
43#include <cstdarg>
44#include <cstdio> // for vsnprintf
45#include "blocxx/Exception.hpp"
46
47
48namespace BLOCXX_NAMESPACE
49{
50
51namespace SafeCString
52{
53#ifdef BLOCXX_WIN32
54#define vsnprintf _vsnprintf
55#endif
56
60 BLOCXX_COMMON_API char * str_dup(char const * s);
61
66 char * str_dup_nothrow(char const * s);
67
68
74 inline char const * nonull(char const * s)
75 {
76 return s ? s : "";
77 }
78
79
95 char * strcpy_trunc(char * dst, std::size_t dstsize, char const * src);
96
112 char * strcpy_trunc(
113 char * dst, std::size_t dstsize, char const * src, std::size_t srclen
114 );
115
119 template <std::size_t N> inline
120 char * strcpy_trunc(char (&dst)[N], char const * src)
121 {
122 return strcpy_trunc(dst, N, src);
123 }
124
128 template <std::size_t N> inline
129 char * strcpy_trunc(char (&dst)[N], char const * src, std::size_t srclen)
130 {
131 return strcpy_trunc(dst, N, src, srclen);
132 }
133
138 template <std::size_t N> inline
140 char (&dst)[N], std::size_t pos, char const * src
141 )
142 {
143 return strcpy_trunc(dst + pos, N - pos, src) - dst;
144 }
145
150 template <std::size_t N> inline
152 char (&dst)[N], std::size_t pos, char const * src, std::size_t srclen
153 )
154 {
155 return strcpy_trunc(dst + pos, N - pos, src, srclen) - dst;
156 }
157
160 int const RESULT_TRUNCATED = 0;
161 int const DEST_UNTERMINATED = 1;
162
180 char * strcpy_check(char * dst, std::size_t dstsize, char const * src);
181
199 char * strcpy_check(
200 char * dst, std::size_t dstsize, char const * src, std::size_t srclen
201 );
202
206 template <std::size_t N> inline
207 char * strcpy_check(char (&dst)[N], char const * src)
208 {
209 return strcpy_check(dst, N, src);
210 }
211
215 template <std::size_t N> inline
216 char * strcpy_check(char (&dst)[N], char const * src, std::size_t srclen)
217 {
218 return strcpy_check(dst, N, src, srclen);
219 }
220
225 template <std::size_t N> inline
227 char (&dst)[N], std::size_t pos, char const * src
228 )
229 {
230 return strcpy_check(dst + pos, N - pos, src) - dst;
231 }
232
237 template <std::size_t N> inline
239 char (&dst)[N], std::size_t pos, char const * src, std::size_t srclen
240 )
241 {
242 return strcpy_check(dst + pos, N - pos, src, srclen) - dst;
243 }
244
245
263 char * strcat_trunc(char * dst, std::size_t dstsize, char const * src);
264
283 char * strcat_trunc(
284 char * dst, std::size_t dstsize, char const * src, std::size_t srclen
285 );
286
290 template <std::size_t N> inline
291 char * strcat_trunc(char (&dst)[N], char const * src)
292 {
293 return strcat_trunc(dst, N, src);
294 }
295
299 template <std::size_t N> inline
300 char * strcat_trunc(char (&dst)[N], char const * src, std::size_t srclen)
301 {
302 return strcat_trunc(dst, N, src, srclen);
303 }
304
326 char * strcat_check(char * dst, std::size_t dstsize, char const * src);
327
350 char * strcat_check(
351 char * dst, std::size_t dstsize, char const * src, std::size_t srclen
352 );
353
357 template <std::size_t N> inline
358 char * strcat_check(char (&dst)[N], char const * src)
359 {
360 return strcat_check(dst, N, src);
361 }
362
366 template <std::size_t N> inline
367 char * strcat_check(char (&dst)[N], char const * src, std::size_t srclen)
368 {
369 return strcat_check(dst, N, src, srclen);
370 }
371
372
373 namespace Impl
374 {
375 inline std::size_t nchars_output(int retval, std::size_t dstsize)
376 {
377 return (
378 retval < 0 || retval >= static_cast<int>(dstsize) ? dstsize - 1
379 : static_cast<std::size_t>(retval)
380 );
381 }
382
383 std::size_t nchars_check(int retval, std::size_t dstsize);
384 }
385
392 template <typename T1>
393 std::size_t sprintf_trunc(
394 char * dst, std::size_t dstsize, char const * fmt, T1 const & x1
395 )
396 {
397 return Impl::nchars_output(snprintf(dst, dstsize, fmt, x1), dstsize);
398 }
399
406 template <typename T1, typename T2>
407 std::size_t sprintf_trunc(
408 char * dst, std::size_t dstsize, char const * fmt,
409 T1 const & x1, T2 const & x2
410 )
411 {
412 return Impl::nchars_output(
413 snprintf(dst, dstsize, fmt, x1, x2), dstsize);
414 }
415
422 template <typename T1, typename T2, typename T3>
423 std::size_t sprintf_trunc(
424 char * dst, std::size_t dstsize, char const * fmt,
425 T1 const & x1, T2 const & x2, T3 const & x3
426 )
427 {
428 return Impl::nchars_output(
429 snprintf(dst, dstsize, fmt, x1, x2, x3), dstsize);
430 }
431
438 template <typename T1, typename T2, typename T3, typename T4>
439 std::size_t sprintf_trunc(
440 char * dst, std::size_t dstsize, char const * fmt,
441 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
442 )
443 {
444 return Impl::nchars_output(
445 snprintf(dst, dstsize, fmt, x1, x2, x3, x4), dstsize);
446 }
447
454 template <typename T1, typename T2, typename T3, typename T4, typename T5>
455 std::size_t sprintf_trunc(
456 char * dst, std::size_t dstsize, char const * fmt,
457 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
458 )
459 {
460 return Impl::nchars_output(
461 snprintf(dst, dstsize, fmt, x1, x2, x3, x4, x5), dstsize);
462 }
463
467 template <std::size_t N, typename T1>
468 std::size_t sprintf_trunc(char (&dst)[N], char const * fmt, T1 const & x1)
469 {
470 return Impl::nchars_output(snprintf(dst, N, fmt, x1), N);
471 }
472
476 template <std::size_t N, typename T1, typename T2>
477 std::size_t sprintf_trunc(
478 char (&dst)[N], char const * fmt, T1 const & x1, T2 const & x2
479 )
480 {
481 return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2), N);
482 }
483
487 template <std::size_t N, typename T1, typename T2, typename T3>
488 std::size_t sprintf_trunc(
489 char (&dst)[N], char const * fmt,
490 T1 const & x1, T2 const & x2, T3 const & x3
491 )
492 {
493 return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2, x3), N);
494 }
495
499 template <std::size_t N, typename T1, typename T2, typename T3, typename T4>
500 std::size_t sprintf_trunc(
501 char (&dst)[N], char const * fmt,
502 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
503 )
504 {
505 return Impl::nchars_output(snprintf(dst, N, fmt, x1, x2, x3, x4), N);
506 }
507
511 template <std::size_t N, typename T1, typename T2, typename T3, typename T4,
512 typename T5>
513 std::size_t sprintf_trunc(
514 char (&dst)[N], char const * fmt,
515 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
516 )
517 {
518 return Impl::nchars_output(
519 snprintf(dst, N, fmt, x1, x2, x3, x4, x5), N);
520 }
521
522
531 template <typename T1>
532 std::size_t sprintf_check(
533 char * dst, std::size_t dstsize, char const * fmt, T1 const & x1
534 )
535 {
536 return Impl::nchars_check(snprintf(dst, dstsize, fmt, x1), dstsize);
537 }
538
547 template <typename T1, typename T2>
548 std::size_t sprintf_check(
549 char * dst, std::size_t dstsize, char const * fmt,
550 T1 const & x1, T2 const & x2
551 )
552 {
553 return Impl::nchars_check(
554 snprintf(dst, dstsize, fmt, x1, x2), dstsize);
555 }
556
565 template <typename T1, typename T2, typename T3>
566 std::size_t sprintf_check(
567 char * dst, std::size_t dstsize, char const * fmt,
568 T1 const & x1, T2 const & x2, T3 const & x3
569 )
570 {
571 return Impl::nchars_check(
572 snprintf(dst, dstsize, fmt, x1, x2, x3), dstsize);
573 }
574
583 template <typename T1, typename T2, typename T3, typename T4>
584 std::size_t sprintf_check(
585 char * dst, std::size_t dstsize, char const * fmt,
586 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
587 )
588 {
589 return Impl::nchars_check(
590 snprintf(dst, dstsize, fmt, x1, x2, x3, x4), dstsize);
591 }
592
601 template <typename T1, typename T2, typename T3, typename T4, typename T5>
602 std::size_t sprintf_check(
603 char * dst, std::size_t dstsize, char const * fmt,
604 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
605 )
606 {
607 return Impl::nchars_check(
608 snprintf(dst, dstsize, fmt, x1, x2, x3, x4, x5), dstsize);
609 }
610
614 template <std::size_t N, typename T1>
615 std::size_t sprintf_check(char (&dst)[N], char const * fmt, T1 const & x1)
616 {
617 return Impl::nchars_check(snprintf(dst, N, fmt, x1), N);
618 }
619
623 template <std::size_t N, typename T1, typename T2>
624 std::size_t sprintf_check(
625 char (&dst)[N], char const * fmt, T1 const & x1, T2 const & x2
626 )
627 {
628 return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2), N);
629 }
630
634 template <std::size_t N, typename T1, typename T2, typename T3>
635 std::size_t sprintf_check(
636 char (&dst)[N], char const * fmt,
637 T1 const & x1, T2 const & x2, T3 const & x3
638 )
639 {
640 return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3), N);
641 }
642
646 template <std::size_t N, typename T1, typename T2, typename T3, typename T4>
647 std::size_t sprintf_check(
648 char (&dst)[N], char const * fmt,
649 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4
650 )
651 {
652 return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3, x4), N);
653 }
654
658 template <std::size_t N, typename T1, typename T2, typename T3, typename T4,
659 typename T5>
660 std::size_t sprintf_check(
661 char (&dst)[N], char const * fmt,
662 T1 const & x1, T2 const & x2, T3 const & x3, T4 const & x4, T5 const & x5
663 )
664 {
665 return Impl::nchars_check(snprintf(dst, N, fmt, x1, x2, x3, x4, x5), N);
666 }
667
668
675 template <typename T1>
676 std::size_t vprintf_trunc(
677 char * dst, std::size_t dstsize, char const * fmt, va_list ap
678 )
679 {
680 return Impl::nchars_output(vsnprintf(dst, dstsize, fmt, ap), dstsize);
681 }
682
686 template <std::size_t N> inline
687 std::size_t vprintf_trunc(char (&dst)[N], char const * fmt, va_list ap)
688 {
689 return vprintf_trunc(dst, N, fmt, ap);
690 }
691
692
701 inline std::size_t vprintf_check(
702 char * dst, std::size_t dstsize, char const * fmt, va_list ap
703 )
704 {
705 return Impl::nchars_check(vsnprintf(dst, dstsize, fmt, ap), dstsize);
706 }
707
711 template <std::size_t N> inline
712 std::size_t vprintf_check(char (&dst)[N], char const * fmt, va_list ap)
713 {
714 return vprintf_check(dst, N, fmt, ap);
715 }
716
717} // namespace SafeCString
718} // namespace BLOCXX_NAMESPACE
719
720#define BLOCXX_INTSTR_AUX(x) # x
721 /*
722 * Use the BLOCXX_INTSTR macro to insert symbolic constants into format strings.
723 * A typical usage would be for a maximum field width when using the
724 * scanf family of functions. For example, suppose that buf is an array of
725 * STRMAX + 1 characters, and STRMAX is a manifest constant. Then one
726 * might write
727 *
728 * sscanf(inpstr, "Name: %." BLOCXX_INTSTR(STRMAX) "s\n", buf);
729 */
730#define BLOCXX_INTSTR(x) BLOCXX_INTSTR_AUX(x)
731
732#endif
#define BLOCXX_DECLARE_EXCEPTION(NAME)
Declare a new exception class named <NAME>Exception that derives from Exception This macro is typical...
std::size_t nchars_output(int retval, std::size_t dstsize)
std::size_t nchars_check(int retval, std::size_t dstsize)
char * str_dup_nothrow(char const *s)
Like std::strdup, except that no-throw new is used to allocate memory and NULL is returned on allocat...
std::size_t strcpy_to_pos_check(char(&dst)[N], std::size_t pos, char const *src)
Like strcpy_check, but the destination is the subarray dst[pos..N-1] and the return value is an array...
char const * nonull(char const *s)
RETURNS: s if s is nonnull, otherwise returns empty string.
std::size_t sprintf_check(char *dst, std::size_t dstsize, char const *fmt, T1 const &x1)
PROMISE: Behaves like sprintf(dst, fmt, ...) except that output stops at dstsize - 1 characters.
char * strcpy_trunc(char *dst, std::size_t dstsize, char const *src)
PROMISE: copies the first n = min(strlen(src), dstsize - 1) characters of C-string src to dst,...
std::size_t vprintf_trunc(char *dst, std::size_t dstsize, char const *fmt, va_list ap)
PROMISE: Behaves like vprintf(dst, fmt, ap) except that output stops at dstsize - 1 characters.
char * str_dup(char const *s)
Like std::strdup, except that new is used to allocate memory.
std::size_t strcpy_to_pos_trunc(char(&dst)[N], std::size_t pos, char const *src)
Like strcpy_trunc, but the destination is the subarray dst[pos..N-1] and the return value is an array...
char * strcpy_check(char *dst, std::size_t dstsize, char const *src)
PROMISE: copies the first n = min(strlen(src), dstsize - 1) chars of the C-string src to dst and appe...
char * strcat_check(char *dst, std::size_t dstsize, char const *src)
PROMISE: If dst[0..dstsize-1] contains a '\0', appends to C-string dst the first min(strlen(src),...
int const RESULT_TRUNCATED
Error codes for use with OverflowException class.
char * strcat_trunc(char *dst, std::size_t dstsize, char const *src)
PROMISE: If dst[0..dstsize-1] contains a '\0', appends to C-string dst the first min(strlen(src),...
std::size_t vprintf_check(char *dst, std::size_t dstsize, char const *fmt, va_list ap)
PROMISE: Behaves like vprintf(dst, fmt, ap) except that output stops at dstsize - 1 characters.
std::size_t sprintf_trunc(char *dst, std::size_t dstsize, char const *fmt, T1 const &x1)
PROMISE: Behaves like sprintf(dst, fmt, ...) except that output stops at dstsize - 1 characters.
Taken from RFC 1321.