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 
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 
48 namespace BLOCXX_NAMESPACE
49 {
50 
51 namespace 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
139  std::size_t strcpy_to_pos_trunc(
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
151  std::size_t strcpy_to_pos_trunc(
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
226  std::size_t strcpy_to_pos_check(
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
238  std::size_t strcpy_to_pos_check(
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