[163] | 1 | /* -*- c++ -*- |
---|
| 2 | |
---|
| 3 | Formatted string class |
---|
| 4 | |
---|
| 5 | This file is part of the dpp library of C++ template classes |
---|
| 6 | |
---|
| 7 | doc: http://diaxen.ssji.net/dpp/index.html |
---|
| 8 | repo: https://www.ssji.net/svn/projets/trunk/libdpp |
---|
| 9 | |
---|
| 10 | This program is free software: you can redistribute it and/or |
---|
| 11 | modify it under the terms of the GNU Lesser General Public License |
---|
| 12 | as published by the Free Software Foundation, either version 3 of |
---|
| 13 | the License, or (at your option) any later version. |
---|
| 14 | |
---|
| 15 | This program is distributed in the hope that it will be useful, but |
---|
| 16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
| 18 | Lesser General Public License for more details. |
---|
| 19 | |
---|
| 20 | You should have received a copy of the GNU Lesser General Public |
---|
| 21 | License along with this program. If not, see |
---|
| 22 | <http://www.gnu.org/licenses/>. |
---|
| 23 | |
---|
| 24 | (c) 2008-2011 Alexandre Becoulet <alexandre.becoulet@free.fr> |
---|
| 25 | |
---|
| 26 | */ |
---|
| 27 | |
---|
| 28 | #ifndef DPP_FSTRING_HH_ |
---|
| 29 | #define DPP_FSTRING_HH_ |
---|
| 30 | |
---|
| 31 | #include <stdarg.h> |
---|
| 32 | #include <stdio.h> |
---|
| 33 | |
---|
| 34 | #include <string> |
---|
| 35 | |
---|
| 36 | /** @file @module{Formatted string} */ |
---|
| 37 | |
---|
| 38 | #ifdef __GNUC__ |
---|
| 39 | # define _DPP_FORMAT_CHK(archetype, string_index, first_to_check) |
---|
| 40 | #else |
---|
| 41 | # define _DPP_FORMAT_CHK(archetype, string_index, first_to_check) \ |
---|
| 42 | __attribute__((format(archetype, string_index, first_to_check))) |
---|
| 43 | #endif |
---|
| 44 | |
---|
| 45 | namespace dpp { |
---|
| 46 | |
---|
| 47 | /** |
---|
| 48 | @short Extended std::string with sprintf family of functions. |
---|
| 49 | @module {Formatted string} |
---|
| 50 | @header dpp/fstring |
---|
| 51 | @main |
---|
| 52 | |
---|
| 53 | This class provides an extension of the @ref std::string class |
---|
| 54 | with @ref sprintf family of functions and constructors, |
---|
| 55 | for those who find @ref std::ostringstream sometimes cumbersome |
---|
| 56 | to use. Yes, I know, it's not type safe. |
---|
| 57 | |
---|
| 58 | Allocation is performed by underlying @ref std::string class and |
---|
| 59 | format string are processed using the @ref ::vsnprintf libc function |
---|
| 60 | with proper buffer size. |
---|
| 61 | */ |
---|
| 62 | class fstring : public std::string |
---|
| 63 | { |
---|
| 64 | public: |
---|
| 65 | /** @multiple @ref std::string standard constructor */ |
---|
| 66 | fstring() |
---|
| 67 | : std::string() |
---|
| 68 | { |
---|
| 69 | } |
---|
| 70 | |
---|
| 71 | explicit fstring(const std::string &str) |
---|
| 72 | : std::string(str) |
---|
| 73 | { |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | /** @This creates a @ref fstring object from char array. Unlike |
---|
| 77 | the @insert {__fstring2__} prototype constructor, @this does |
---|
| 78 | not perform formatting; initialization with buffer containing |
---|
| 79 | conversion specifiers is safe to use. */ |
---|
| 80 | fstring(const char *str) |
---|
| 81 | : std::string(str) |
---|
| 82 | { |
---|
| 83 | } |
---|
| 84 | |
---|
| 85 | #ifdef __MKDOC__ |
---|
| 86 | /** @This creates a @ref fstring object from format string and |
---|
| 87 | associated arguments. Up to 16 extra arguments can be passed. |
---|
| 88 | @alias fstring2 |
---|
| 89 | */ |
---|
| 90 | fstring(const char *str, ...); |
---|
| 91 | |
---|
| 92 | #else // mkdoc:skip |
---|
| 93 | |
---|
| 94 | #define _DPP_FSTRING_CSTR(b, c, ...) \ |
---|
| 95 | _DPP_FORMAT_CHK(printf, 1, 2) \ |
---|
| 96 | template <__VA_ARGS__> \ |
---|
| 97 | fstring b \ |
---|
| 98 | { \ |
---|
| 99 | dpp::fstring::sprintf c; \ |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0), |
---|
| 103 | (fmt, a0), |
---|
| 104 | typename A0) |
---|
| 105 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1), |
---|
| 106 | (fmt, a0, a1), |
---|
| 107 | typename A0, typename A1) |
---|
| 108 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2), |
---|
| 109 | (fmt, a0, a1, a2), |
---|
| 110 | typename A0, typename A1, typename A2) |
---|
| 111 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3), |
---|
| 112 | (fmt, a0, a1, a2, a3), |
---|
| 113 | typename A0, typename A1, typename A2, typename A3) |
---|
| 114 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4), |
---|
| 115 | (fmt, a0, a1, a2, a3, a4), |
---|
| 116 | typename A0, typename A1, typename A2, typename A3, typename A4) |
---|
| 117 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5), |
---|
| 118 | (fmt, a0, a1, a2, a3, a4, a5), |
---|
| 119 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5) |
---|
| 120 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6), |
---|
| 121 | (fmt, a0, a1, a2, a3, a4, a5, a6), |
---|
| 122 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6) |
---|
| 123 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7), |
---|
| 124 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7), |
---|
| 125 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7) |
---|
| 126 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8), |
---|
| 127 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8), |
---|
| 128 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8) |
---|
| 129 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9), |
---|
| 130 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), |
---|
| 131 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9) |
---|
| 132 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10), |
---|
| 133 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10), |
---|
| 134 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10) |
---|
| 135 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10, const A11 &a11), |
---|
| 136 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11), |
---|
| 137 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11) |
---|
| 138 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10, const A11 &a11, const A12 &a12), |
---|
| 139 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12), |
---|
| 140 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12) |
---|
| 141 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10, const A11 &a11, const A12 &a12, const A13 &a13), |
---|
| 142 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13), |
---|
| 143 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13) |
---|
| 144 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10, const A11 &a11, const A12 &a12, const A13 &a13, const A14 &a14), |
---|
| 145 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14), |
---|
| 146 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14) |
---|
| 147 | _DPP_FSTRING_CSTR((const char *fmt, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9, const A10 &a10, const A11 &a11, const A12 &a12, const A13 &a13, const A14 &a14, const A15 &a15), |
---|
| 148 | (fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15), |
---|
| 149 | typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15) |
---|
| 150 | #endif |
---|
| 151 | |
---|
| 152 | /** @This preallocates a string of given size and creates a @ref |
---|
| 153 | fstring from format string and associated arguments. */ |
---|
| 154 | _DPP_FORMAT_CHK(printf, 1, 3) |
---|
| 155 | fstring(size_t size, const char *fmt, ...) |
---|
| 156 | { |
---|
| 157 | va_list ap; |
---|
| 158 | va_start(ap, fmt); |
---|
| 159 | dpp::fstring::vsnprintf(size, fmt, ap); |
---|
| 160 | va_end(ap); |
---|
| 161 | } |
---|
| 162 | |
---|
| 163 | /** @This overwrites current content using format string and |
---|
| 164 | associated arguments. */ |
---|
| 165 | int vsprintf(const char *fmt, va_list ap) |
---|
| 166 | { |
---|
| 167 | int s; |
---|
| 168 | va_list aq; |
---|
| 169 | |
---|
| 170 | va_copy(aq, ap); |
---|
| 171 | if (empty()) |
---|
| 172 | s = ::vsnprintf(NULL, 0, fmt, aq); |
---|
| 173 | else |
---|
| 174 | s = ::vsnprintf(&at(0), size() + 1, fmt, aq); |
---|
| 175 | |
---|
| 176 | if (s >= 0 && s > (int)size()) |
---|
| 177 | { |
---|
| 178 | resize(s); |
---|
| 179 | s = ::vsnprintf(&at(0), size() + 1, fmt, ap); |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | va_end(aq); |
---|
| 183 | return s; |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | /** @This resizes current buffer and overwrite its content |
---|
| 187 | using format string and associated arguments. */ |
---|
| 188 | int vsnprintf(size_t size, const char *fmt, va_list ap) |
---|
| 189 | { |
---|
| 190 | resize(size); |
---|
| 191 | return ::vsnprintf(&at(0), size + 1, fmt, ap); |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | /** @This overwrites current content using format string and |
---|
| 195 | associated arguments. */ |
---|
| 196 | _DPP_FORMAT_CHK(printf, 1, 2) |
---|
| 197 | int sprintf(const char *fmt, ...) |
---|
| 198 | { |
---|
| 199 | va_list ap; |
---|
| 200 | int res; |
---|
| 201 | va_start(ap, fmt); |
---|
| 202 | res = dpp::fstring::vsprintf(fmt, ap); |
---|
| 203 | va_end(ap); |
---|
| 204 | return res; |
---|
| 205 | } |
---|
| 206 | |
---|
| 207 | /** @This resizes current buffer and overwrite its content |
---|
| 208 | using format string and associated arguments. */ |
---|
| 209 | _DPP_FORMAT_CHK(printf, 1, 3) |
---|
| 210 | int snprintf(size_t size, const char *fmt, ...) |
---|
| 211 | { |
---|
| 212 | va_list ap; |
---|
| 213 | int res; |
---|
| 214 | va_start(ap, fmt); |
---|
| 215 | res = dpp::fstring::vsnprintf(size, fmt, ap); |
---|
| 216 | va_end(ap); |
---|
| 217 | return res; |
---|
| 218 | } |
---|
| 219 | |
---|
| 220 | /** @This returns the buffer content as a @tt{const char *}. @see c_str */ |
---|
| 221 | operator const char *() { |
---|
| 222 | return c_str(); |
---|
| 223 | } |
---|
| 224 | |
---|
| 225 | /** @This returns the buffer content as a @tt{const char *}. @see c_str */ |
---|
| 226 | const char * operator+() { |
---|
| 227 | return c_str(); |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | }; |
---|
| 231 | |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | #endif |
---|
| 235 | |
---|