@@ -667,27 +667,238 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
667
667
668
668
struct BuiltStyledStreamWriter : public StreamWriter
669
669
{
670
- mutable StyledStreamWriter old_;
671
-
672
670
BuiltStyledStreamWriter (
673
671
std::ostream* sout,
674
672
std::string const & indentation,
675
673
StreamWriter::CommentStyle cs);
676
674
virtual int write (Value const & root) const ;
675
+ private:
676
+ void writeValue (const Value& value);
677
+ void writeArrayValue (const Value& value);
678
+ bool isMultineArray (const Value& value);
679
+ void pushValue (const std::string& value);
680
+ void writeIndent ();
681
+ void writeWithIndent (const std::string& value);
682
+ void indent ();
683
+ void unindent ();
684
+ void writeCommentBeforeValue (const Value& root);
685
+ void writeCommentAfterValueOnSameLine (const Value& root);
686
+ bool hasCommentForValue (const Value& value);
687
+ static std::string normalizeEOL (const std::string& text);
688
+
689
+ typedef std::vector<std::string> ChildValues;
690
+
691
+ ChildValues childValues_;
692
+ std::ostream* document_;
693
+ std::string indentString_;
694
+ int rightMargin_;
695
+ std::string indentation_;
696
+ bool addChildValues_;
677
697
};
678
698
BuiltStyledStreamWriter::BuiltStyledStreamWriter (
679
699
std::ostream* sout,
680
700
std::string const & indentation,
681
701
StreamWriter::CommentStyle cs)
682
702
: StreamWriter(sout)
683
- , old_(indentation)
703
+ , indentation_(indentation)
704
+ , rightMargin_(74 )
684
705
{
685
706
}
686
707
int BuiltStyledStreamWriter::write (Value const & root) const
687
708
{
688
- old_. write (sout_, root);
709
+ write (sout_, root);
689
710
return 0 ;
690
711
}
712
+ void BuiltStyledStreamWriter::write (std::ostream& out, const Value& root) {
713
+ document_ = &out;
714
+ addChildValues_ = false ;
715
+ indentString_ = " " ;
716
+ writeCommentBeforeValue (root);
717
+ writeValue (root);
718
+ writeCommentAfterValueOnSameLine (root);
719
+ *document_ << " \n " ;
720
+ document_ = NULL ; // Forget the stream, for safety.
721
+ }
722
+
723
+ void BuiltStyledStreamWriter::writeValue (const Value& value) {
724
+ switch (value.type ()) {
725
+ case nullValue:
726
+ pushValue (" null" );
727
+ break ;
728
+ case intValue:
729
+ pushValue (valueToString (value.asLargestInt ()));
730
+ break ;
731
+ case uintValue:
732
+ pushValue (valueToString (value.asLargestUInt ()));
733
+ break ;
734
+ case realValue:
735
+ pushValue (valueToString (value.asDouble ()));
736
+ break ;
737
+ case stringValue:
738
+ pushValue (valueToQuotedString (value.asCString ()));
739
+ break ;
740
+ case booleanValue:
741
+ pushValue (valueToString (value.asBool ()));
742
+ break ;
743
+ case arrayValue:
744
+ writeArrayValue (value);
745
+ break ;
746
+ case objectValue: {
747
+ Value::Members members (value.getMemberNames ());
748
+ if (members.empty ())
749
+ pushValue (" {}" );
750
+ else {
751
+ writeWithIndent (" {" );
752
+ indent ();
753
+ Value::Members::iterator it = members.begin ();
754
+ for (;;) {
755
+ const std::string& name = *it;
756
+ const Value& childValue = value[name];
757
+ writeCommentBeforeValue (childValue);
758
+ writeWithIndent (valueToQuotedString (name.c_str ()));
759
+ *document_ << " : " ;
760
+ writeValue (childValue);
761
+ if (++it == members.end ()) {
762
+ writeCommentAfterValueOnSameLine (childValue);
763
+ break ;
764
+ }
765
+ *document_ << " ," ;
766
+ writeCommentAfterValueOnSameLine (childValue);
767
+ }
768
+ unindent ();
769
+ writeWithIndent (" }" );
770
+ }
771
+ } break ;
772
+ }
773
+ }
774
+
775
+ void BuiltStyledStreamWriter::writeArrayValue (const Value& value) {
776
+ unsigned size = value.size ();
777
+ if (size == 0 )
778
+ pushValue (" []" );
779
+ else {
780
+ bool isArrayMultiLine = isMultineArray (value);
781
+ if (isArrayMultiLine) {
782
+ writeWithIndent (" [" );
783
+ indent ();
784
+ bool hasChildValue = !childValues_.empty ();
785
+ unsigned index = 0 ;
786
+ for (;;) {
787
+ const Value& childValue = value[index];
788
+ writeCommentBeforeValue (childValue);
789
+ if (hasChildValue)
790
+ writeWithIndent (childValues_[index]);
791
+ else {
792
+ writeIndent ();
793
+ writeValue (childValue);
794
+ }
795
+ if (++index == size) {
796
+ writeCommentAfterValueOnSameLine (childValue);
797
+ break ;
798
+ }
799
+ *document_ << " ," ;
800
+ writeCommentAfterValueOnSameLine (childValue);
801
+ }
802
+ unindent ();
803
+ writeWithIndent (" ]" );
804
+ } else // output on a single line
805
+ {
806
+ assert (childValues_.size () == size);
807
+ *document_ << " [ " ;
808
+ for (unsigned index = 0 ; index < size; ++index) {
809
+ if (index > 0 )
810
+ *document_ << " , " ;
811
+ *document_ << childValues_[index];
812
+ }
813
+ *document_ << " ]" ;
814
+ }
815
+ }
816
+ }
817
+
818
+ bool BuiltStyledStreamWriter::isMultineArray (const Value& value) {
819
+ int size = value.size ();
820
+ bool isMultiLine = size * 3 >= rightMargin_;
821
+ childValues_.clear ();
822
+ for (int index = 0 ; index < size && !isMultiLine; ++index) {
823
+ const Value& childValue = value[index];
824
+ isMultiLine =
825
+ isMultiLine || ((childValue.isArray () || childValue.isObject ()) &&
826
+ childValue.size () > 0 );
827
+ }
828
+ if (!isMultiLine) // check if line length > max line length
829
+ {
830
+ childValues_.reserve (size);
831
+ addChildValues_ = true ;
832
+ int lineLength = 4 + (size - 1 ) * 2 ; // '[ ' + ', '*n + ' ]'
833
+ for (int index = 0 ; index < size; ++index) {
834
+ writeValue (value[index]);
835
+ lineLength += int (childValues_[index].length ());
836
+ }
837
+ addChildValues_ = false ;
838
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
839
+ }
840
+ return isMultiLine;
841
+ }
842
+
843
+ void BuiltStyledStreamWriter::pushValue (const std::string& value) {
844
+ if (addChildValues_)
845
+ childValues_.push_back (value);
846
+ else
847
+ *document_ << value;
848
+ }
849
+
850
+ void BuiltStyledStreamWriter::writeIndent () {
851
+ /*
852
+ Some comments in this method would have been nice. ;-)
853
+
854
+ if ( !document_.empty() )
855
+ {
856
+ char last = document_[document_.length()-1];
857
+ if ( last == ' ' ) // already indented
858
+ return;
859
+ if ( last != '\n' ) // Comments may add new-line
860
+ *document_ << '\n';
861
+ }
862
+ */
863
+ *document_ << ' \n ' << indentString_;
864
+ }
865
+
866
+ void BuiltStyledStreamWriter::writeWithIndent (const std::string& value) {
867
+ writeIndent ();
868
+ *document_ << value;
869
+ }
870
+
871
+ void BuiltStyledStreamWriter::indent () { indentString_ += indentation_; }
872
+
873
+ void BuiltStyledStreamWriter::unindent () {
874
+ assert (indentString_.size () >= indentation_.size ());
875
+ indentString_.resize (indentString_.size () - indentation_.size ());
876
+ }
877
+
878
+ void BuiltStyledStreamWriter::writeCommentBeforeValue (const Value& root) {
879
+ if (!root.hasComment (commentBefore))
880
+ return ;
881
+ *document_ << root.getComment (commentBefore);
882
+ *document_ << " \n " ;
883
+ }
884
+
885
+ void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine (const Value& root) {
886
+ if (root.hasComment (commentAfterOnSameLine))
887
+ *document_ << " " + root.getComment (commentAfterOnSameLine);
888
+
889
+ if (root.hasComment (commentAfter)) {
890
+ *document_ << " \n " ;
891
+ *document_ << root.getComment (commentAfter);
892
+ *document_ << " \n " ;
893
+ }
894
+ }
895
+
896
+ bool BuiltStyledStreamWriter::hasCommentForValue (const Value& value) {
897
+ return value.hasComment (commentBefore) ||
898
+ value.hasComment (commentAfterOnSameLine) ||
899
+ value.hasComment (commentAfter);
900
+ }
901
+
691
902
StreamWriter::StreamWriter (std::ostream* sout)
692
903
: sout_(*sout)
693
904
{
0 commit comments