Otclient  14/8/2020
format.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #ifndef STDEXT_FORMAT_H
24 #define STDEXT_FORMAT_H
25 
26 #include "traits.h"
27 
28 #include <string>
29 #include <cstdio>
30 #include <cassert>
31 #include <tuple>
32 #include <iostream>
33 #include <sstream>
34 #include <iomanip>
35 
36 namespace stdext {
37 
38 template<class T> void print_ostream(std::ostringstream& stream, const T& last) { stream << last; }
39 template<class T, class... Args>
40 void print_ostream(std::ostringstream& stream, const T& first, const Args&... rest) { stream << "\t" << first; print_ostream(stream, rest...); }
41 template<class... T>
42 
43 // Utility for printing variables just like lua
44 void print(const T&... args) { std::ostringstream buf; print_ostream(buf, args...); std::cout << buf.str() << std::endl; }
45 
46 template<typename T>
47 typename std::enable_if<std::is_integral<T>::value ||
48  std::is_pointer<T>::value ||
49  std::is_floating_point<T>::value ||
50  std::is_enum<T>::value, T>::type sprintf_cast(const T& t) { return t; }
51 inline const char *sprintf_cast(const char *s) { return s; }
52 inline const char *sprintf_cast(const std::string& s) { return s.c_str(); }
53 
54 template<int N> struct expand_snprintf {
55  template<typename Tuple, typename... Args> static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
56  return expand_snprintf<N-1>::call(s, maxlen, format, tuple, sprintf_cast(std::get<N-1>(tuple)), args...); }};
57 template<> struct expand_snprintf<0> {
58  template<typename Tuple, typename... Args> static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
59 #ifdef _MSC_VER
60  return _snprintf(s, maxlen, format, args...);
61 #else
62  return snprintf(s, maxlen, format, args...);
63 #endif
64  }
65 };
66 
67 // Improved snprintf that accepts std::string and other types
68 template<typename... Args>
69 int snprintf(char *s, size_t maxlen, const char *format, const Args&... args) {
70  std::tuple<typename replace_extent<Args>::type...> tuple(args...);
71  return expand_snprintf<std::tuple_size<decltype(tuple)>::value>::call(s, maxlen, format, tuple);
72 }
73 
74 template<typename... Args>
75 inline int snprintf(char *s, size_t maxlen, const char *format) {
76  std::strncpy(s, format, maxlen);
77  s[maxlen-1] = 0;
78  return strlen(s);
79 }
80 
81 template<typename... Args>
82 inline std::string format() { return std::string(); }
83 
84 template<typename... Args>
85 inline std::string format(const std::string& format) { return format; }
86 
87 // Format strings with the sprintf style, accepting std::string and string convertible types for %s
88 template<typename... Args>
89 std::string format(const std::string& format, const Args&... args) {
90  int n, size = 1024;
91  std::string str;
92  while(true) {
93  str.resize(size);
94  n = snprintf(&str[0], size, format.c_str(), args...);
95  assert(n != -1);
96  if(n < size) {
97  str.resize(n);
98  return str;
99  }
100  size *= 2;
101  }
102 }
103 
104 }
105 
106 #endif
stdext::sprintf_cast
std::enable_if< std::is_integral< T >::value||std::is_pointer< T >::value||std::is_floating_point< T >::value||std::is_enum< T >::value, T >::type sprintf_cast(const T &t)
Definition: format.h:50
stdext::expand_snprintf::call
static int call(char *s, size_t maxlen, const char *format, const Tuple &tuple, const Args &... args)
Definition: format.h:55
stdext::print_ostream
void print_ostream(std::ostringstream &stream, const T &last)
Definition: format.h:38
stdext::expand_snprintf
Definition: format.h:54
stdext::expand_snprintf< 0 >::call
static int call(char *s, size_t maxlen, const char *format, const Tuple &tuple, const Args &... args)
Definition: format.h:58
stdext::format
std::string format()
Definition: format.h:82
stdext::snprintf
int snprintf(char *s, size_t maxlen, const char *format, const Args &... args)
Definition: format.h:69
stdext::print
void print(const T &... args)
Definition: format.h:44
traits.h
stdext
Definition: any.h:30