A library for working with phylogenetic and population genetic data.
v0.27.0
utils/formats/json/writer.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2020 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
32 
33 #include <cassert>
34 #include <fstream>
35 #include <ostream>
36 #include <stdexcept>
37 
43 
44 namespace genesis {
45 namespace utils {
46 
47 // =================================================================================================
48 // Writing
49 // =================================================================================================
50 
51 void JsonWriter::write( JsonDocument const& document, std::shared_ptr<utils::BaseOutputTarget> target ) const
52 {
53  auto& os = target->ostream();
54  print_value( document, os );
55 }
56 
57 std::string JsonWriter::to_string( JsonDocument const& document ) const
58 {
59  std::stringstream sstr;
60  print_value( document, sstr );
61  return sstr.str();
62 }
63 
64 // =================================================================================================
65 // Printing
66 // =================================================================================================
67 
68 void JsonWriter::print_value(
69  JsonDocument const& value,
70  std::ostream& out
71 ) const {
72  switch(value.type()) {
74  out << "null";
75  break;
76  }
78  out << ( value.get_boolean() ? "true" : "false" );
79  break;
80  }
82  out << to_string_precise( value.get_number_float(), precision_ );
83  break;
84  }
86  out << value.get_number_signed();
87  break;
88  }
90  out << value.get_number_unsigned();
91  break;
92  }
94  out << "\"" + utils::escape( value.get_string() ) + "\"";
95  break;
96  }
98  print_array( value, out, 0 );
99  break;
100  }
102  print_object( value, out, 0 );
103  break;
104  }
105  default: {
106  assert( false );
107  }
108  }
109 }
110 
111 void JsonWriter::print_array(
112  JsonDocument const& value,
113  std::ostream& out,
114  int indent_level
115 ) const {
116  int il = indent_level + 1;
117  std::string in (il * indent_, ' ');
118 
119  // Check if array contains non-primitive values.
120  // If so, we use better bracket placement to make document look nicer.
121  bool has_large = false;
122  for( auto const& elem : value ) {
123  has_large |= ( elem.is_array() || elem.is_object());
124  }
125 
126  out << "[ ";
127  bool first = true;
128  for( auto const& elem : value ) {
129  if (!first) {
130  out << ", ";
131  }
132  if (has_large) {
133  out << "\n" << in;
134  }
135  if (elem.is_array()) {
136  print_array( elem, out, il );
137  } else if ( elem.is_object() ) {
138  print_object( elem, out, il );
139  } else {
140  print_value( elem, out );
141  }
142  first = false;
143  }
144 
145  if (has_large) {
146  out << "\n" << std::string(indent_level * indent_, ' ');
147  } else {
148  out << " ";
149  }
150  out << "]";
151 }
152 
153 void JsonWriter::print_object(
154  JsonDocument const& value,
155  std::ostream& out,
156  int indent_level
157 ) const {
158  int il = indent_level + 1;
159  std::string in (il * indent_, ' ');
160  out << "{";
161 
162  bool first = true;
163  for( auto it = value.begin(); it != value.end(); ++it ) {
164  if (!first) {
165  out << ",";
166  }
167  out << "\n" << in << "\"" << it.key() << "\": ";
168  if ( it.value().is_array() ) {
169  print_array( it.value(), out, il );
170  } else if( it.value().is_object() ) {
171  print_object( it.value(), out, il );
172  } else {
173  print_value( it.value(), out );
174  }
175  first = false;
176  }
177 
178  out << "\n" << std::string(indent_level * indent_, ' ') << "}";
179 }
180 
181 } // namespace utils
182 } // namespace genesis
genesis::utils::JsonDocument::ValueType::kNumberFloat
@ kNumberFloat
genesis::utils::JsonDocument::ValueType::kString
@ kString
genesis::utils::JsonDocument::ValueType::kNull
@ kNull
genesis::utils::JsonWriter::to_string
std::string to_string(JsonDocument const &document) const
Return the Json representation of a JsonDocument.
Definition: utils/formats/json/writer.cpp:57
fs.hpp
Provides functions for accessing the file system.
genesis::utils::JsonDocument::get_number_float
NumberFloatType & get_number_float()
Definition: json/document.cpp:381
genesis::utils::JsonWriter::write
void write(JsonDocument const &document, std::shared_ptr< utils::BaseOutputTarget > target) const
Write a JsonDocument to an output target, using the JSON format.
Definition: utils/formats/json/writer.cpp:51
output_stream.hpp
genesis::utils::JsonDocument
Store a Json value of any kind.
Definition: json/document.hpp:114
genesis::utils::JsonDocument::ValueType::kNumberSigned
@ kNumberSigned
genesis::utils::to_string_precise
std::string to_string_precise(double const value, int const precision)
Return a precise string representation of the input value, using the provided precision value (determ...
Definition: string.cpp:778
genesis::utils::JsonDocument::type
ValueType type() const
Return the type of the JSON value.
Definition: json/document.hpp:585
genesis::utils::JsonDocument::get_number_unsigned
NumberUnsignedType & get_number_unsigned()
Definition: json/document.cpp:413
string.hpp
Provides some commonly used string utility functions.
genesis::utils::JsonDocument::ValueType::kObject
@ kObject
document.hpp
genesis::utils::JsonDocument::ValueType::kNumberUnsigned
@ kNumberUnsigned
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::JsonDocument::get_string
StringType & get_string()
Definition: json/document.cpp:349
genesis::utils::JsonDocument::ValueType::kBoolean
@ kBoolean
iterator.hpp
genesis::utils::JsonDocument::get_boolean
BooleanType & get_boolean()
Definition: json/document.cpp:365
genesis::utils::JsonDocument::get_number_signed
NumberSignedType & get_number_signed()
Definition: json/document.cpp:397
genesis::utils::JsonDocument::ValueType::kArray
@ kArray
writer.hpp
genesis::utils::escape
std::string escape(std::string const &text)
Return a string where special chars are replaces by their escape sequence.
Definition: string.cpp:703