A library for working with phylogenetic and population genetic data.
v0.27.0
json/document.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2019 Lucas Czech and HITS gGmbH
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 
24 /*
25  The code in this and the following source files is a heavily altered adaption of the excellent
26  "JSON for Modern C++" library by Niels Lohmann, see https://github.com/nlohmann/json
27 
28  * lib/utils/formats/json/document.hpp
29  * lib/utils/formats/json/document.cpp
30  * lib/utils/formats/json/iterator.hpp
31 
32  We adapted the original code by splitting it into different classes, using our naming convention
33  and name spaces, removed not needed functionality and wrote our own reading/parsing routines.
34 
35  For the files listed above, we need to include the following original license:
36 
37  MIT License
38 
39  Copyright (c) 2013-2017 Niels Lohmann
40 
41  Permission is hereby granted, free of charge, to any person obtaining a copy
42  of this software and associated documentation files (the "Software"), to deal
43  in the Software without restriction, including without limitation the rights
44  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45  copies of the Software, and to permit persons to whom the Software is
46  furnished to do so, subject to the following conditions:
47 
48  The above copyright notice and this permission notice shall be included in all
49  copies or substantial portions of the Software.
50 
51  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57  SOFTWARE.
58  */
59 
68 
71 
72 #include <algorithm>
73 #include <array>
74 
75 namespace genesis {
76 namespace utils {
77 
78 // =================================================================================================
79 // Constructors and Rule of Five
80 // =================================================================================================
81 
82 // ---------------------------------------------------------------------
83 // Initializer List Constructor
84 // ---------------------------------------------------------------------
85 
87  std::initializer_list<JsonDocument> init,
88  bool type_deduction,
89  ValueType manual_type
90 ) {
91 
92  // Check if each element is an array with two elements, whose first element is a string
93  bool is_an_object = std::all_of(
94  init.begin(),
95  init.end(),
96  []( JsonDocument const& element ) {
97  return element.is_array() and element.size() == 2 and element[0].is_string();
98  }
99  );
100 
101  // Adjust type if type deduction is not wanted
102  if( not type_deduction ) {
103  // if array is wanted, do not create an object though possible
104  if( manual_type == ValueType::kArray ) {
105  is_an_object = false;
106  }
107 
108  // if object is wanted but impossible, throw an exception
109  if( manual_type == ValueType::kObject and not is_an_object ) {
110  throw std::domain_error( "Invalid initializer list for creating Json object ." );
111  }
112  }
113 
114  if( is_an_object ) {
115  // the initializer list is a list of pairs -> create object
116  type_ = ValueType::kObject;
117  value_ = ValueType::kObject;
118 
119  std::for_each(
120  init.begin(),
121  init.end(),
122  [this] ( JsonDocument const& element ) {
123  value_.object->emplace( *(element[0].value_.string), element[1] );
124  }
125  );
126 
127  } else {
128  // the initializer list describes an array -> create array
129  type_ = ValueType::kArray;
130  value_.array = create<ArrayType>( init );
131  }
132 
133  assert_invariant();
134 }
135 
136 // ---------------------------------------------------------------------
137 // Copy Constructor
138 // ---------------------------------------------------------------------
139 
141  : type_( other.type_ )
142 {
143  // Check that the passed value is valid
144  other.assert_invariant();
145 
146  switch ( type_ ) {
147  case ValueType::kObject: {
148  value_ = *other.value_.object;
149  break;
150  }
151  case ValueType::kArray: {
152  value_ = *other.value_.array;
153  break;
154  }
155  case ValueType::kString: {
156  value_ = *other.value_.string;
157  break;
158  }
159  case ValueType::kBoolean: {
160  value_ = other.value_.boolean;
161  break;
162  }
164  value_ = other.value_.number_float;
165  break;
166  }
168  value_ = other.value_.number_signed;
169  break;
170  }
172  value_ = other.value_.number_unsigned;
173  break;
174  }
175  default: {
176  break;
177  }
178  }
179 
180  assert_invariant();
181 }
182 
183 // ---------------------------------------------------------------------
184 // Move Constructor
185 // ---------------------------------------------------------------------
186 
188  : type_( std::move( other.type_ ))
189  , value_( std::move( other.value_ ))
190 {
191  // Check that passed value is valid
192  other.assert_invariant();
193 
194  // Invalidate payload
195  other.type_ = ValueType::kNull;
196  other.value_ = {};
197 
198  assert_invariant();
199 }
200 
201 // ---------------------------------------------------------------------
202 // Copy Assignment
203 // ---------------------------------------------------------------------
204 
206 {
207  // check that passed value is valid
208  other.assert_invariant();
209 
210  // Use copy swap idion (with copy being done in the signature).
211  using std::swap;
212  swap( type_, other.type_ );
213  swap( value_, other.value_ );
214 
215  assert_invariant();
216  return *this;
217 }
218 
219 // ---------------------------------------------------------------------
220 // Destructor
221 // ---------------------------------------------------------------------
222 
224 {
225  assert_invariant();
226 
227  switch( type_ ) {
228  case ValueType::kArray: {
229  destroy<ArrayType>( value_.array );
230  break;
231  }
232  case ValueType::kObject: {
233  destroy<ObjectType>( value_.object );
234  break;
235  }
236  case ValueType::kString: {
237  destroy<StringType>( value_.string );
238  break;
239  }
240  default: {
241  // Nothing to do for other types.
242  break;
243  }
244  }
245 }
246 
247 // =================================================================================================
248 // Capacity
249 // =================================================================================================
250 
252 {
253  switch( type_ ) {
254  case ValueType::kNull: {
255  // null values are empty
256  return true;
257  }
258  case ValueType::kArray: {
259  // delegate call to ArrayType::empty()
260  return value_.array->empty();
261  }
262  case ValueType::kObject: {
263  // delegate call to ObjectType::empty()
264  return value_.object->empty();
265  }
266  default: {
267  // all other types are nonempty
268  return false;
269  }
270  }
271 }
272 
273 size_t JsonDocument::size() const
274 {
275  switch( type_ ) {
276  case ValueType::kNull: {
277  // null values are empty
278  return 0;
279  }
280  case ValueType::kArray: {
281  // delegate call to ArrayType::size()
282  return value_.array->size();
283  }
284  case ValueType::kObject: {
285  // delegate call to ObjectType::size()
286  return value_.object->size();
287  }
288  default: {
289  // all other types have size 1
290  return 1;
291  }
292  }
293 }
294 
296 {
297  switch( type_ ) {
298  case ValueType::kArray: {
299  // delegate call to ArrayType::max_size()
300  return value_.array->max_size();
301  }
302  case ValueType::kObject: {
303  // delegate call to ObjectType::max_size()
304  return value_.object->max_size();
305  }
306  default: {
307  // all other types have max_size() == size()
308  return size();
309  }
310  }
311 }
312 
313 // =================================================================================================
314 // Value Access
315 // =================================================================================================
316 
318 {
319  if( not is_array() ) {
320  throw std::domain_error( "Cannot use get_array() with " + type_name() + "." );
321  }
322  return *value_.array;
323 }
324 
326 {
327  if( not is_array() ) {
328  throw std::domain_error( "Cannot use get_array() with " + type_name() + "." );
329  }
330  return *value_.array;
331 }
332 
334 {
335  if( not is_object() ) {
336  throw std::domain_error( "Cannot use get_object() with " + type_name() + "." );
337  }
338  return *value_.object;
339 }
340 
342 {
343  if( not is_object() ) {
344  throw std::domain_error( "Cannot use get_object() with " + type_name() + "." );
345  }
346  return *value_.object;
347 }
348 
350 {
351  if( not is_string() ) {
352  throw std::domain_error( "Cannot use get_string() with " + type_name() + "." );
353  }
354  return *value_.string;
355 }
356 
358 {
359  if( not is_string() ) {
360  throw std::domain_error( "Cannot use get_string() with " + type_name() + "." );
361  }
362  return *value_.string;
363 }
364 
366 {
367  if( not is_boolean() ) {
368  throw std::domain_error( "Cannot use get_boolean() with " + type_name() + "." );
369  }
370  return value_.boolean;
371 }
372 
374 {
375  if( not is_boolean() ) {
376  throw std::domain_error( "Cannot use get_boolean() with " + type_name() + "." );
377  }
378  return value_.boolean;
379 }
380 
382 {
383  if( not is_number_float() ) {
384  throw std::domain_error( "Cannot use get_number_float() with " + type_name() + "." );
385  }
386  return value_.number_float;
387 }
388 
390 {
391  if( not is_number_float() ) {
392  throw std::domain_error( "Cannot use get_number_float() with " + type_name() + "." );
393  }
394  return value_.number_float;
395 }
396 
398 {
399  if( not is_number_signed() ) {
400  throw std::domain_error( "Cannot use get_number_signed() with " + type_name() + "." );
401  }
402  return value_.number_signed;
403 }
404 
406 {
407  if( not is_number_signed() ) {
408  throw std::domain_error( "Cannot use get_number_signed() with " + type_name() + "." );
409  }
410  return value_.number_signed;
411 }
412 
414 {
415  if( not is_number_unsigned() ) {
416  throw std::domain_error( "Cannot use get_number_unsigned() with " + type_name() + "." );
417  }
418  return value_.number_unsigned;
419 }
420 
422 {
423  if( not is_number_unsigned() ) {
424  throw std::domain_error( "Cannot use get_number_unsigned() with " + type_name() + "." );
425  }
426  return value_.number_unsigned;
427 }
428 
429 // =================================================================================================
430 // Element Access
431 // =================================================================================================
432 
434 {
435  // This code is also copied to the const version of the function.
436  if( is_array() ) {
437  try{
438  return value_.array->at( index );
439  } catch( ... ) {
440  throw std::out_of_range(
441  "Array index " + std::to_string( index ) + " is out of range."
442  );
443  }
444  } else {
445  throw std::domain_error( "Cannot use at() with " + type_name() );
446  }
447 }
448 
449 JsonDocument const& JsonDocument::at( size_t index ) const
450 {
451  // Copied from non-const version of the function.
452  if( is_array() ) {
453  try{
454  return value_.array->at( index );
455  } catch( ... ) {
456  throw std::out_of_range(
457  "Array index " + std::to_string( index ) + " is out of range."
458  );
459  }
460  } else {
461  throw std::domain_error( "Cannot use at() with " + type_name() );
462  }
463 }
464 
465 JsonDocument& JsonDocument::at( typename ObjectType::key_type const& key )
466 {
467  // This code is also copied to the const version of the function.
468  if( is_object() ) {
469  try{
470  return value_.object->at( key );
471  } catch( ... ) {
472  throw std::out_of_range(
473  "Invalid key '" + key + "' for object access."
474  );
475  }
476  } else {
477  throw std::domain_error( "Cannot use at() with " + type_name() );
478  }
479 }
480 
481 JsonDocument const& JsonDocument::at( typename ObjectType::key_type const& key ) const
482 {
483  // Copied from non-const version of the function.
484  if( is_object() ) {
485  try{
486  return value_.object->at( key );
487  } catch( ... ) {
488  throw std::out_of_range(
489  "Invalid key '" + key + "' for object access."
490  );
491  }
492  } else {
493  throw std::domain_error( "Cannot use at() with " + type_name() );
494  }
495 }
496 
498 {
499  // Implicitly convert null value to an empty array
500  if( is_null( )) {
501  type_ = ValueType::kArray;
502  value_.array = create<ArrayType>();
503  assert_invariant();
504  }
505 
506  if( is_array() ) {
507  // fill up array with null values if given idx is outside range
508  if( index >= value_.array->size() ) {
509  value_.array->insert(
510  value_.array->end(),
511  index - value_.array->size() + 1,
512  JsonDocument()
513  );
514  }
515 
516  return value_.array->operator[]( index );
517  } else {
518  throw std::domain_error( "Cannot use operator[] with " + type_name() );
519  }
520 }
521 
522 JsonDocument const& JsonDocument::operator [] ( size_t index ) const
523 {
524  if( is_array() ) {
525  return value_.array->operator[]( index );
526  } else {
527  throw std::domain_error( "Cannot use operator[] with " + type_name() );
528  }
529 }
530 
531 JsonDocument& JsonDocument::operator [] ( typename ObjectType::key_type const& key )
532 {
533  // implicitly convert null value to an empty object
534  if( is_null() ) {
535  type_ = ValueType::kObject;
536  value_.object = create<ObjectType>();
537  assert_invariant();
538  }
539 
540  // operator[] only works for objects
541  if( is_object() ) {
542  return value_.object->operator[]( key );
543  } else {
544  throw std::domain_error( "Cannot use operator[] with " + type_name() );
545  }
546 }
547 
548 JsonDocument const& JsonDocument::operator [] ( typename ObjectType::key_type const& key ) const
549 {
550  // const operator[] only works for objects
551  if( is_object() ) {
552  assert(value_.object->find(key) != value_.object->end());
553  return value_.object->find(key)->second;
554  } else {
555  throw std::domain_error( "Cannot use operator[] with " + type_name() );
556  }
557 }
558 
559 // =================================================================================================
560 // Lookup
561 // =================================================================================================
562 
563 JsonDocument::iterator JsonDocument::find( typename JsonDocument::ObjectType::key_type key )
564 {
565  auto result = end();
566  if( is_object() ) {
567  result.iterator_.object_iterator = value_.object->find(key);
568  }
569  return result;
570 }
571 
572 JsonDocument::const_iterator JsonDocument::find(typename JsonDocument::ObjectType::key_type key) const
573 {
574  auto result = cend();
575  if( is_object() ) {
576  result.iterator_.object_iterator = value_.object->find(key);
577  }
578  return result;
579 }
580 
581 JsonDocument::size_type JsonDocument::count(typename JsonDocument::ObjectType::key_type key) const
582 {
583  // return 0 for all nonobject types
584  return is_object() ? value_.object->count(key) : 0;
585 }
586 
587 // =================================================================================================
588 // Iterators
589 // =================================================================================================
590 
592 {
593  iterator result(this);
594  result.set_begin();
595  return result;
596 }
597 
599 {
600  return cbegin();
601 }
602 
604 {
605  const_iterator result(this);
606  result.set_begin();
607  return result;
608 }
609 
611 {
612  iterator result(this);
613  result.set_end();
614  return result;
615 }
616 
618 {
619  return cend();
620 }
621 
623 {
624  const_iterator result(this);
625  result.set_end();
626  return result;
627 }
628 
629 // =================================================================================================
630 // Modifiers
631 // =================================================================================================
632 
634 {
635  switch( type_ ) {
637  value_.number_signed = 0;
638  break;
639  }
641  value_.number_unsigned = 0;
642  break;
643  }
645  value_.number_float = 0.0;
646  break;
647  }
648  case ValueType::kBoolean: {
649  value_.boolean = false;
650  break;
651  }
652  case ValueType::kString: {
653  value_.string->clear();
654  break;
655  }
656  case ValueType::kArray: {
657  value_.array->clear();
658  break;
659  }
660  case ValueType::kObject: {
661  value_.object->clear();
662  break;
663  }
664  default: {
665  break;
666  }
667  }
668 }
669 
671 {
672  // push_back only works for null objects or arrays
673  if( not(is_null() or is_array()) ) {
674  throw std::domain_error("Cannot use push_back() with " + type_name());
675  }
676 
677  // transform null object into an array
678  if( is_null() ) {
679  type_ = ValueType::kArray;
680  value_ = ValueType::kArray;
681  assert_invariant();
682  }
683 
684  // add element to array (move semantics)
685  value_.array->push_back(std::move(val));
686  // invalidate object
687  val.type_ = ValueType::kNull;
688 }
689 
691 {
692  // push_back only works for null objects or arrays
693  if( not(is_null() or is_array()) ) {
694  throw std::domain_error("cannot use push_back() with " + type_name());
695  }
696 
697  // transform null object into an array
698  if( is_null() ) {
699  type_ = ValueType::kArray;
700  value_ = ValueType::kArray;
701  assert_invariant();
702  }
703 
704  // add element to array
705  value_.array->push_back(val);
706 }
707 
708 void JsonDocument::push_back( typename ObjectType::value_type const& val )
709 {
710  // push_back only works for null objects or objects
711  if( not(is_null() or is_object()) ) {
712  throw std::domain_error("Cannot use push_back() with " + type_name());
713  }
714 
715  // transform null object into an object
716  if( is_null() ) {
717  type_ = ValueType::kObject;
718  value_ = ValueType::kObject;
719  assert_invariant();
720  }
721 
722  // add element to array
723  value_.object->insert(val);
724 }
725 
726 // =================================================================================================
727 // Lexicographical Comparison Operators
728 // =================================================================================================
729 
731 {
732  const auto lhs_type = lhs.type();
733  const auto rhs_type = rhs.type();
734 
735  // Shorthands
736  using ValueType = JsonDocument::ValueType;
737  using NumberFloatType = JsonDocument::NumberFloatType;
738  using NumberSignedType = JsonDocument::NumberSignedType;
739 
740  if( lhs_type == rhs_type ) {
741  switch( lhs_type ) {
742  case ValueType::kArray: {
743  return *lhs.value_.array == *rhs.value_.array;
744  }
745  case ValueType::kObject: {
746  return *lhs.value_.object == *rhs.value_.object;
747  }
748  case ValueType::kNull: {
749  return true;
750  }
751  case ValueType::kString: {
752  return *lhs.value_.string == *rhs.value_.string;
753  }
754  case ValueType::kBoolean: {
755  return lhs.value_.boolean == rhs.value_.boolean;
756  }
757  case ValueType::kNumberSigned: {
758  return lhs.value_.number_signed == rhs.value_.number_signed;
759  }
760  case ValueType::kNumberUnsigned: {
761  return lhs.value_.number_unsigned == rhs.value_.number_unsigned;
762  }
763  case ValueType::kNumberFloat: {
764  return lhs.value_.number_float == rhs.value_.number_float;
765  }
766  default: {
767  return false;
768  }
769  }
770  }
771  else if( lhs_type == ValueType::kNumberSigned and rhs_type == ValueType::kNumberFloat ) {
772  return static_cast<NumberFloatType>(lhs.value_.number_signed) == rhs.value_.number_float;
773  }
774  else if( lhs_type == ValueType::kNumberFloat and rhs_type == ValueType::kNumberSigned ) {
775  return lhs.value_.number_float == static_cast<NumberFloatType>(rhs.value_.number_signed);
776  }
777  else if( lhs_type == ValueType::kNumberUnsigned and rhs_type == ValueType::kNumberFloat ) {
778  return static_cast<NumberFloatType>(lhs.value_.number_unsigned) == rhs.value_.number_float;
779  }
780  else if( lhs_type == ValueType::kNumberFloat and rhs_type == ValueType::kNumberUnsigned ) {
781  return lhs.value_.number_float == static_cast<NumberFloatType>(rhs.value_.number_unsigned);
782  }
783  else if( lhs_type == ValueType::kNumberUnsigned and rhs_type == ValueType::kNumberSigned ) {
784  return static_cast<NumberSignedType>(lhs.value_.number_unsigned) == rhs.value_.number_signed;
785  }
786  else if( lhs_type == ValueType::kNumberSigned and rhs_type == ValueType::kNumberUnsigned ) {
787  return lhs.value_.number_signed == static_cast<NumberSignedType>(rhs.value_.number_unsigned);
788  }
789 
790  return false;
791 }
792 
794 {
795  const auto lhs_type = lhs.type();
796  const auto rhs_type = rhs.type();
797 
798  // Shorthands
799  using ValueType = JsonDocument::ValueType;
800  using NumberFloatType = JsonDocument::NumberFloatType;
801  using NumberSignedType = JsonDocument::NumberSignedType;
802 
803  if( lhs_type == rhs_type ) {
804  switch( lhs_type ) {
805  case ValueType::kArray: {
806  return *lhs.value_.array < *rhs.value_.array;
807  }
808  case ValueType::kObject: {
809  return *lhs.value_.object < *rhs.value_.object;
810  }
811  case ValueType::kNull: {
812  return false;
813  }
814  case ValueType::kString: {
815  return *lhs.value_.string < *rhs.value_.string;
816  }
817  case ValueType::kBoolean: {
818  return lhs.value_.boolean < rhs.value_.boolean;
819  }
820  case ValueType::kNumberSigned: {
821  return lhs.value_.number_signed < rhs.value_.number_signed;
822  }
823  case ValueType::kNumberUnsigned: {
824  return lhs.value_.number_unsigned < rhs.value_.number_unsigned;
825  }
826  case ValueType::kNumberFloat: {
827  return lhs.value_.number_float < rhs.value_.number_float;
828  }
829  default: {
830  return false;
831  }
832  }
833  }
834  else if( lhs_type == ValueType::kNumberSigned and rhs_type == ValueType::kNumberFloat ) {
835  return static_cast<NumberFloatType>(lhs.value_.number_signed) < rhs.value_.number_float;
836  }
837  else if( lhs_type == ValueType::kNumberFloat and rhs_type == ValueType::kNumberSigned ) {
838  return lhs.value_.number_float < static_cast<NumberFloatType>(rhs.value_.number_signed);
839  }
840  else if( lhs_type == ValueType::kNumberUnsigned and rhs_type == ValueType::kNumberFloat ) {
841  return static_cast<NumberFloatType>(lhs.value_.number_unsigned) < rhs.value_.number_float;
842  }
843  else if( lhs_type == ValueType::kNumberFloat and rhs_type == ValueType::kNumberUnsigned ) {
844  return lhs.value_.number_float < static_cast<NumberFloatType>(rhs.value_.number_unsigned);
845  }
846  else if( lhs_type == ValueType::kNumberSigned and rhs_type == ValueType::kNumberUnsigned ) {
847  return lhs.value_.number_signed < static_cast<NumberSignedType>(rhs.value_.number_unsigned);
848  }
849  else if( lhs_type == ValueType::kNumberUnsigned and rhs_type == ValueType::kNumberSigned ) {
850  return static_cast<NumberSignedType>(lhs.value_.number_unsigned) < rhs.value_.number_signed;
851  }
852 
853  // We only reach this line if we cannot compare values. In that case,
854  // we compare types. Note we have to call the operator explicitly,
855  // because MSVC has problems otherwise.
856  return operator<(lhs_type, rhs_type);
857 }
858 
860 {
861  // Use the order of the ValueType enum!
862  static std::array<uint8_t, 8> order = {{
863  0, // null
864  4, // array
865  3, // object
866  5, // string
867  1, // boolean
868  2, // float
869  2, // signed
870  2, // unsigned
871  }
872  };
873  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
874 }
875 
876 // =================================================================================================
877 // Convenience Functions
878 // =================================================================================================
879 
880 std::string JsonDocument::type_name() const
881 {
882  switch( type_ ) {
883  case ValueType::kNull: {
884  return "null";
885  }
886  case ValueType::kArray: {
887  return "array";
888  }
889  case ValueType::kObject: {
890  return "object";
891  }
892  case ValueType::kString: {
893  return "string";
894  }
895  case ValueType::kBoolean: {
896  return "boolean";
897  }
899  return "float";
900  }
902  return "signed integer";
903  }
905  return "unsigned integer";
906  }
907  default: {
908  // Can only happen if we misuse the type somewhere.
909  // Make gcc happy by returning something here.
910  assert( false );
911  return "invalid type";
912  }
913  };
914 }
915 
916 } // namespace utils
917 } // namespace genesis
genesis::utils::JsonDocument::ValueType::kNumberFloat
@ kNumberFloat
genesis::utils::JsonDocument::ValueType::kString
@ kString
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::utils::JsonDocument::cbegin
const_iterator cbegin() const
Return a const iterator to the first element.
Definition: json/document.cpp:603
genesis::utils::JsonDocument::count
size_type count(typename ObjectType::key_type key) const
Return the number of occurrences of a key in a JSON object.
Definition: json/document.cpp:581
genesis::utils::JsonDocument::ValueType::kNull
@ kNull
genesis::utils::JsonDocument::get_object
ObjectType & get_object()
Definition: json/document.cpp:333
genesis::utils::JsonDocument::get_number_float
NumberFloatType & get_number_float()
Definition: json/document.cpp:381
genesis::utils::JsonDocument::JsonDocument
JsonDocument(std::nullptr_t=nullptr)
Create a null object.
Definition: json/document.hpp:269
genesis::utils::JsonDocument::end
iterator end()
Return an iterator to one past the last element.
Definition: json/document.cpp:610
genesis::utils::JsonDocument::find
iterator find(typename JsonDocument::ObjectType::key_type key)
Find an element in a JSON object.
Definition: json/document.cpp:563
genesis::utils::JsonDocument
Store a Json value of any kind.
Definition: json/document.hpp:114
genesis::utils::JsonDocument::size_type
std::size_t size_type
Definition: json/document.hpp:140
genesis::utils::JsonDocument::type_name
std::string type_name() const
Definition: json/document.cpp:880
genesis::utils::JsonDocument::ArrayType
std::vector< JsonDocument > ArrayType
Definition: json/document.hpp:142
genesis::utils::JsonDocument::is_null
bool is_null() const
Return true iff the JSON value is null.
Definition: json/document.hpp:609
genesis::utils::JsonDocument::ValueType::kNumberSigned
@ kNumberSigned
genesis::utils::JsonDocument::begin
iterator begin()
Return an iterator to the first element.
Definition: json/document.cpp:591
genesis::utils::JsonDocument::get_number_unsigned
NumberUnsignedType & get_number_unsigned()
Definition: json/document.cpp:413
genesis::utils::JsonDocument::is_number_unsigned
bool is_number_unsigned() const
Return true iff the JSON value is an unsigned integer number.
Definition: json/document.hpp:682
genesis::utils::JsonDocument::ValueType
ValueType
Definition: json/document.hpp:151
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: functions/genome_locus.hpp:48
genesis::utils::JsonDocument::~JsonDocument
~JsonDocument()
Destructor.
Definition: json/document.cpp:223
genesis::utils::JsonDocument::BooleanType
bool BooleanType
Definition: json/document.hpp:146
genesis::utils::JsonDocument::max_size
size_t max_size() const
Definition: json/document.cpp:295
genesis::utils::JsonDocument::ValueType::kObject
@ kObject
genesis::utils::JsonDocument::const_reference
JsonDocument const & const_reference
Definition: json/document.hpp:131
genesis::utils::JsonDocument::NumberFloatType
double NumberFloatType
Definition: json/document.hpp:147
logging.hpp
Provides easy and fast logging functionality.
genesis::utils::JsonDocument::push_back
void push_back(JsonDocument &&val)
Add a Json value to an array.
Definition: json/document.cpp:670
document.hpp
genesis::utils::JsonDocument::is_boolean
bool is_boolean() const
Return true iff the JSON value is a boolean.
Definition: json/document.hpp:641
genesis::utils::JsonDocument::at
JsonDocument & at(size_t index)
Definition: json/document.cpp:433
genesis::utils::JsonDocument::is_number_float
bool is_number_float() const
Return true iff the JSON value is a float number.
Definition: json/document.hpp:658
genesis::utils::JsonDocument::is_array
bool is_array() const
Return true iff the JSON value is an array.
Definition: json/document.hpp:617
genesis::utils::JsonDocument::size
size_t size() const
Definition: json/document.cpp:273
genesis::utils::JsonDocument::ValueType::kNumberUnsigned
@ kNumberUnsigned
genesis::utils::JsonDocument::operator[]
JsonDocument & operator[](size_t index)
Definition: json/document.cpp:497
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::is_number_signed
bool is_number_signed() const
Return true iff the JSON value is a signed integer number.
Definition: json/document.hpp:674
genesis::utils::JsonDocument::clear
void clear()
Clears the content of a JSON value and resets it to the default value as if JsonDocument(ValueType) w...
Definition: json/document.cpp:633
genesis::utils::JsonDocument::StringType
std::string StringType
Definition: json/document.hpp:144
genesis::utils::JsonDocument::is_string
bool is_string() const
Return true iff the JSON value is a string.
Definition: json/document.hpp:633
genesis::utils::JsonDocument::cend
const_iterator cend() const
Return a const iterator to one past the last element.
Definition: json/document.cpp:622
genesis::utils::operator<
bool operator<(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:386
genesis::utils::JsonDocument::NumberUnsignedType
std::uint64_t NumberUnsignedType
Definition: json/document.hpp:149
genesis::utils::JsonDocument::operator=
JsonDocument & operator=(JsonDocument other)
Copy assignment.
Definition: json/document.cpp:205
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::empty
bool empty() const
Definition: json/document.cpp:251
genesis::utils::operator==
bool operator==(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:374
genesis::utils::JsonDocument::ObjectType
std::map< std::string, JsonDocument > ObjectType
Definition: json/document.hpp:143
genesis::utils::JsonDocument::get_array
ArrayType & get_array()
Definition: json/document.cpp:317
genesis::utils::swap
void swap(Optional< T > &x, Optional< T > &y)
Definition: optional.hpp:566
genesis::utils::JsonDocument::get_number_signed
NumberSignedType & get_number_signed()
Definition: json/document.cpp:397
genesis::utils::JsonDocument::ValueType::kArray
@ kArray
genesis::utils::JsonDocument::NumberSignedType
std::int64_t NumberSignedType
Definition: json/document.hpp:148
genesis::utils::JsonDocument::is_object
bool is_object() const
Return true iff the JSON value is an object.
Definition: json/document.hpp:625
genesis::utils::JsonIterator
Template for a random access iterator for the JsonDocument class.
Definition: json/document.hpp:88