Skip to content

Commit 47f13a0

Browse files
committed
Start adding support for custom output types
1 parent 64d343a commit 47f13a0

File tree

3 files changed

+95
-25
lines changed

3 files changed

+95
-25
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The [example](example.cpp) covers all the features in the library:
2727

2828
int main()
2929
{
30+
using json_printer = jpr::json_printer;
3031
const auto pretty_print = true; // trade output size for readability
3132
const auto indent = 2; // indentation level when pretty-printing
3233
json_printer out(std::cout, pretty_print, indent);

example.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
int main()
99
{
10+
using json_printer = jpr::json_printer;
1011
const auto pretty_print = true; // trade output size for readability
1112
const auto indent = 2; // indentation level when pretty-printing
1213
json_printer out(std::cout, pretty_print, indent);

json_printer.hpp

Lines changed: 93 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,22 @@
2828

2929
#include <cstddef>
3030
#include <iostream>
31+
#include <sstream>
3132
#include <stack>
3233
#include <type_traits>
3334

3435

36+
namespace jpr {
37+
38+
3539
class json_printer {
3640
public:
3741
enum container_type { object, array };
3842

3943
json_printer(std::ostream &os = std::cout, bool pretty = false,
40-
int indent = 2)
41-
: os_(os), pretty_(pretty), indent_(indent), have_separator_(true)
44+
int indent = 2, int base_nesting = 0)
45+
: os_(os), pretty_(pretty), indent_(indent),
46+
base_nesting_(base_nesting), have_separator_(true)
4247
{
4348
print(object);
4449
}
@@ -90,6 +95,8 @@ class json_printer {
9095
return *this;
9196
}
9297

98+
std::ostream &ostream() noexcept { return os_; }
99+
93100
private:
94101
void start_print()
95102
{
@@ -129,37 +136,98 @@ class json_printer {
129136
}
130137

131138
template <typename T>
132-
typename std::enable_if<!std::is_integral<T>::value &&
133-
!std::is_floating_point<T>::value>::type
134-
escape_and_print(const T &value)
135-
{
136-
os_ << '"' << value << '"';
137-
}
138-
139-
template <typename T>
140-
typename std::enable_if<std::is_integral<T>::value ||
141-
std::is_floating_point<T>::value>::type
142-
escape_and_print(const T &value)
143-
{
144-
os_ << value;
145-
}
146-
147-
void escape_and_print(bool value) { os_ << (value ? "true" : "false"); }
148-
149-
void escape_and_print(nullptr_t) { os_ << "null"; }
150-
151-
void escape_and_print(container_type t)
152-
{
153-
os_ << (t == object ? '{' : '[');
154-
}
139+
inline void escape_and_print(const T &value);
155140

156141
std::ostream &os_;
157142
bool pretty_;
158143
int indent_;
144+
int base_nesting_;
159145
bool have_separator_;
160146
bool need_newline_;
161147
std::stack<container_type> nesting_info_;
162148
};
163149

164150

151+
namespace detail {
152+
153+
154+
template <typename T>
155+
typename std::enable_if<std::is_integral<T>::value ||
156+
std::is_floating_point<T>::value>::type
157+
print_as_json(json_printer &printer, T value)
158+
{
159+
printer.ostream() << value;
160+
}
161+
162+
void print_as_json(json_printer &printer, const std::string &value)
163+
{
164+
auto &os = printer.ostream();
165+
os << '"';
166+
for (const auto c : value) {
167+
switch (c) {
168+
case '\\': os << "\\\\"; break;
169+
case '\"': os << "\\\""; break;
170+
default: os << c;
171+
}
172+
}
173+
os << '"';
174+
}
175+
176+
void print_as_json(json_printer &printer, const char *value)
177+
{
178+
print_as_json(printer, std::string(value));
179+
}
180+
181+
void print_as_json(json_printer &printer, bool value)
182+
{ printer.ostream() << (value ? "true" : "false"); }
183+
184+
void print_as_json(json_printer &printer, std::nullptr_t) { printer.ostream() << "null"; }
185+
186+
void print_as_json(json_printer &printer, json_printer::container_type t)
187+
{
188+
printer.ostream() << (t == json_printer::object ? '{' : '[');
189+
}
190+
191+
192+
template <typename...>
193+
using void_t = void;
194+
195+
196+
template <typename T, typename = void>
197+
struct have_custom_printer : std::false_type {};
198+
199+
template <typename T>
200+
struct have_custom_printer<T, void_t<decltype(print_as_json(std::declval<json_printer&>(), std::declval<T>()))>> : std::true_type {};
201+
202+
203+
template <typename T>
204+
typename std::enable_if<have_custom_printer<T>::value>::type
205+
escape_and_print_impl(json_printer &printer, const T &value)
206+
{
207+
print_as_json(printer, value);
208+
}
209+
210+
template <typename T>
211+
typename std::enable_if<!have_custom_printer<T>::value>::type
212+
escape_and_print_impl(json_printer &printer, const T &value)
213+
{
214+
std::ostringstream ss;
215+
ss << value;
216+
print_as_json(printer, ss.str());
217+
}
218+
219+
220+
} // namespace detail
221+
222+
223+
template <typename T>
224+
void json_printer::escape_and_print(const T &value)
225+
{
226+
detail::escape_and_print_impl(*this, value);
227+
}
228+
229+
230+
} // namespace jpr
231+
232+
165233
#endif // JSON_PRINTER_HPP_

0 commit comments

Comments
 (0)