Apache Mesos
format.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_FORMAT_HPP__
14 #define __STOUT_FORMAT_HPP__
15 
16 #include <stdarg.h> // For 'va_list', 'va_start', 'va_end'.
17 
18 // For 'vasprintf'.
19 #ifdef __WINDOWS__
20 #include <stout/windows/format.hpp>
21 #else
22 #include <stdio.h>
23 #endif // __WINDOWS__
24 
25 #include <string>
26 #include <type_traits> // For 'is_pod'.
27 
28 #include <stout/error.hpp>
29 #include <stout/stringify.hpp>
30 #include <stout/try.hpp>
31 
32 
33 // The 'strings::format' functions produces strings based on the
34 // printf family of functions. Except, unlike the printf family of
35 // functions, the 'strings::format' routines attempt to "stringify"
36 // any arguments that are not POD types (i.e., "plain old data":
37 // primitives, pointers, certain structs/classes and unions,
38 // etc). This enables passing structs/classes to 'strings::format'
39 // provided there is a definition/specialization of 'ostream::operator
40 // <<' available for that type. Note that the '%s' format specifier is
41 // expected for each argument that gets stringified. A specialization
42 // for std::string is also provided so that std::string::c_str is not
43 // necessary (but again, '%s' is expected as the format specifier).
44 
45 namespace strings {
46 namespace internal {
47 
48 Try<std::string> format(const std::string& fmt, va_list args);
49 Try<std::string> format(const std::string fmt, ...);
50 
51 template <typename T, bool b>
52 struct stringify;
53 
54 } // namespace internal {
55 
56 
57 template <typename... T>
58 Try<std::string> format(const std::string& s, const T&... t)
59 {
60  return internal::format(
61  s,
62  internal::stringify<T, !std::is_pod<T>::value>(t).get()...);
63 }
64 
65 
66 namespace internal {
67 
68 inline Try<std::string> format(const std::string& fmt, va_list args)
69 {
70  char* temp;
71  if (vasprintf(&temp, fmt.c_str(), args) == -1) {
72  // Note that temp is undefined, so we do not need to call free.
73  return Error("Failed to format '" + fmt + "' (possibly out of memory)");
74  }
75  std::string result(temp);
76  free(temp);
77  return result;
78 }
79 
80 
81 // NOTE: 'fmt' cannot be 'const std::string&' because passing an
82 // argument of reference type as the second argument of 'va_start'
83 // results in undefined behavior.
84 // Refer to http://stackoverflow.com/a/222314 for further details.
85 inline Try<std::string> format(const std::string fmt, ...)
86 {
87  va_list args;
88  va_start(args, fmt);
89  const Try<std::string> result = format(fmt, args);
90  va_end(args);
91  return result;
92 }
93 
94 
95 template <typename T>
96 struct stringify<T, false>
97 {
98  stringify(const T& _t) : t(_t) {}
99  const T& get() { return t; }
100  const T& t;
101 };
102 
103 
104 template <typename T>
105 struct stringify<T, true>
106 {
107  stringify(const T& _t) : s(::stringify(_t)) {}
108  const char* get() { return s.c_str(); }
109 
110  // NOTE: We need to do the copy here, because the temporary returned by
111  // ::stringify() doesn't outlive the get() call inside strings::format().
112  // TODO(vinod): Figure out a fix for using const ref here.
113  const std::string s;
114 };
115 
116 
117 template <>
118 struct stringify<std::string, true>
119 {
120  stringify(const std::string& _s) : s(_s) {}
121  const char* get() { return s.c_str(); }
122  const std::string& s;
123 };
124 
125 } // namespace internal {
126 } // namespace strings {
127 
128 #endif // __STOUT_FORMAT_HPP__
stringify(const T &_t)
Definition: format.hpp:107
Definition: errorbase.hpp:36
const std::string & s
Definition: format.hpp:122
Definition: check.hpp:33
Definition: format.hpp:45
const std::string s
Definition: format.hpp:113
Definition: type_utils.hpp:619
Definition: format.hpp:52
stringify(const T &_t)
Definition: format.hpp:98
Definition: attributes.hpp:24
const T & t
Definition: format.hpp:100
std::string temp()
Definition: temp.hpp:27
Try< std::string > format(const std::string &fmt, va_list args)
Definition: format.hpp:68
stringify(const std::string &_s)
Definition: format.hpp:120
int vasprintf(char **buffer, const char *format, va_list args)
Definition: format.hpp:47