38 #include <plugin/json_server/json/writer.h>
49 static bool isControlCharacter(
char ch)
51 return ch > 0 && ch <= 0x1F;
54 static bool containsControlCharacter(
const char* str )
58 if ( isControlCharacter( *(str++) ) )
63 static void uintToString(
unsigned int value,
69 *--current = (value % 10) +
'0';
75 std::string valueToString( Int value )
78 char *current = buffer +
sizeof(buffer);
79 bool isNegative = value < 0;
82 uintToString( UInt(value), current );
85 assert( current >= buffer );
90 std::string valueToString( UInt value )
93 char *current = buffer +
sizeof(buffer);
94 uintToString( value, current );
95 assert( current >= buffer );
99 std::string valueToString(
double value )
102 #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
103 sprintf_s(buffer,
sizeof(buffer),
"%#.16g", value);
105 sprintf(buffer,
"%#.16g", value);
107 char* ch = buffer + strlen(buffer) - 1;
108 if (*ch !=
'0')
return buffer;
109 while(ch > buffer && *ch ==
'0'){
112 char* last_nonzero = ch;
129 *(last_nonzero+2) =
'\0';
139 std::string valueToString(
bool value )
141 return value ?
"true" :
"false";
144 std::string valueToQuotedString(
const char *value )
147 if (strpbrk(value,
"\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
148 return std::string(
"\"") + value +
"\"";
152 unsigned maxsize = strlen(value)*2 + 3;
154 result.reserve(maxsize);
156 for (
const char* c=value; *c != 0; ++c)
190 if ( isControlCharacter( *c ) )
192 std::ostringstream oss;
193 oss <<
"\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
217 FastWriter::FastWriter()
218 : yamlCompatiblityEnabled_( false )
224 FastWriter::enableYAMLCompatibility()
226 yamlCompatiblityEnabled_ =
true;
231 FastWriter::write(
const Value &root )
241 FastWriter::writeValue(
const Value &value )
243 switch ( value.type() )
249 document_ += valueToString( value.asInt() );
252 document_ += valueToString( value.asUInt() );
255 document_ += valueToString( value.asDouble() );
258 document_ += valueToQuotedString( value.asCString() );
261 document_ += valueToString( value.asBool() );
266 int size = value.size();
267 for (
int index =0; index < size; ++index )
271 writeValue( value[index] );
278 Value::Members members( value.getMemberNames() );
280 for ( Value::Members::iterator it = members.begin();
284 const std::string &name = *it;
285 if ( it != members.begin() )
287 document_ += valueToQuotedString( name.c_str() );
288 document_ += yamlCompatiblityEnabled_ ?
": "
290 writeValue( value[name] );
302 StyledWriter::StyledWriter()
313 addChildValues_ =
false;
315 writeCommentBeforeValue( root );
317 writeCommentAfterValueOnSameLine( root );
324 StyledWriter::writeValue(
const Value &value )
326 switch ( value.type() )
332 pushValue( valueToString( value.asInt() ) );
335 pushValue( valueToString( value.asUInt() ) );
338 pushValue( valueToString( value.asDouble() ) );
341 pushValue( valueToQuotedString( value.asCString() ) );
344 pushValue( valueToString( value.asBool() ) );
347 writeArrayValue( value);
352 if ( members.empty() )
356 writeWithIndent(
"{" );
358 Value::Members::iterator it = members.begin();
361 const std::string &name = *it;
362 const Value &childValue = value[name];
363 writeCommentBeforeValue( childValue );
364 writeWithIndent( valueToQuotedString( name.c_str() ) );
366 writeValue( childValue );
367 if ( ++it == members.end() )
369 writeCommentAfterValueOnSameLine( childValue );
373 writeCommentAfterValueOnSameLine( childValue );
376 writeWithIndent(
"}" );
385 StyledWriter::writeArrayValue(
const Value &value )
387 unsigned size = value.size();
392 bool isArrayMultiLine = isMultineArray( value );
393 if ( isArrayMultiLine )
395 writeWithIndent(
"[" );
397 bool hasChildValue = !childValues_.empty();
401 const Value &childValue = value[index];
402 writeCommentBeforeValue( childValue );
404 writeWithIndent( childValues_[index] );
408 writeValue( childValue );
410 if ( ++index == size )
412 writeCommentAfterValueOnSameLine( childValue );
416 writeCommentAfterValueOnSameLine( childValue );
419 writeWithIndent(
"]" );
423 assert( childValues_.size() == size );
425 for (
unsigned index =0; index < size; ++index )
429 document_ += childValues_[index];
438 StyledWriter::isMultineArray(
const Value &value )
440 int size = value.size();
441 bool isMultiLine = size*3 >= rightMargin_ ;
442 childValues_.clear();
443 for (
int index =0; index < size && !isMultiLine; ++index )
445 const Value &childValue = value[index];
446 isMultiLine = isMultiLine ||
447 ( (childValue.isArray() || childValue.isObject()) &&
448 childValue.size() > 0 );
452 childValues_.reserve( size );
453 addChildValues_ =
true;
454 int lineLength = 4 + (size-1)*2;
455 for (
int index =0; index < size && !isMultiLine; ++index )
457 writeValue( value[index] );
458 lineLength += int( childValues_[index].length() );
459 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
461 addChildValues_ =
false;
462 isMultiLine = isMultiLine || lineLength >= rightMargin_;
469 StyledWriter::pushValue(
const std::string &value )
471 if ( addChildValues_ )
472 childValues_.push_back( value );
479 StyledWriter::writeIndent()
481 if ( !document_.empty() )
483 char last = document_[document_.length()-1];
489 document_ += indentString_;
494 StyledWriter::writeWithIndent(
const std::string &value )
502 StyledWriter::indent()
504 indentString_ += std::string( indentSize_,
' ' );
509 StyledWriter::unindent()
511 assert(
int(indentString_.size()) >= indentSize_ );
512 indentString_.resize( indentString_.size() - indentSize_ );
517 StyledWriter::writeCommentBeforeValue(
const Value &root )
521 document_ += normalizeEOL( root.getComment(
commentBefore ) );
527 StyledWriter::writeCommentAfterValueOnSameLine(
const Value &root )
535 document_ += normalizeEOL( root.getComment(
commentAfter ) );
542 StyledWriter::hasCommentForValue(
const Value &value )
551 StyledWriter::normalizeEOL(
const std::string &text )
553 std::string normalized;
554 normalized.reserve( text.length() );
555 const char *begin = text.c_str();
556 const char *end = begin + text.length();
557 const char *current = begin;
558 while ( current != end )
563 if ( *current ==
'\n' )
577 StyledStreamWriter::StyledStreamWriter( std::string indentation )
580 , indentation_( indentation )
589 addChildValues_ =
false;
591 writeCommentBeforeValue( root );
593 writeCommentAfterValueOnSameLine( root );
600 StyledStreamWriter::writeValue(
const Value &value )
602 switch ( value.type() )
608 pushValue( valueToString( value.asInt() ) );
611 pushValue( valueToString( value.asUInt() ) );
614 pushValue( valueToString( value.asDouble() ) );
617 pushValue( valueToQuotedString( value.asCString() ) );
620 pushValue( valueToString( value.asBool() ) );
623 writeArrayValue( value);
628 if ( members.empty() )
632 writeWithIndent(
"{" );
634 Value::Members::iterator it = members.begin();
637 const std::string &name = *it;
638 const Value &childValue = value[name];
639 writeCommentBeforeValue( childValue );
640 writeWithIndent( valueToQuotedString( name.c_str() ) );
642 writeValue( childValue );
643 if ( ++it == members.end() )
645 writeCommentAfterValueOnSameLine( childValue );
649 writeCommentAfterValueOnSameLine( childValue );
652 writeWithIndent(
"}" );
661 StyledStreamWriter::writeArrayValue(
const Value &value )
663 unsigned size = value.size();
668 bool isArrayMultiLine = isMultineArray( value );
669 if ( isArrayMultiLine )
671 writeWithIndent(
"[" );
673 bool hasChildValue = !childValues_.empty();
677 const Value &childValue = value[index];
678 writeCommentBeforeValue( childValue );
680 writeWithIndent( childValues_[index] );
684 writeValue( childValue );
686 if ( ++index == size )
688 writeCommentAfterValueOnSameLine( childValue );
692 writeCommentAfterValueOnSameLine( childValue );
695 writeWithIndent(
"]" );
699 assert( childValues_.size() == size );
701 for (
unsigned index =0; index < size; ++index )
705 *document_ << childValues_[index];
714 StyledStreamWriter::isMultineArray(
const Value &value )
716 int size = value.size();
717 bool isMultiLine = size*3 >= rightMargin_ ;
718 childValues_.clear();
719 for (
int index =0; index < size && !isMultiLine; ++index )
721 const Value &childValue = value[index];
722 isMultiLine = isMultiLine ||
723 ( (childValue.isArray() || childValue.isObject()) &&
724 childValue.size() > 0 );
728 childValues_.reserve( size );
729 addChildValues_ =
true;
730 int lineLength = 4 + (size-1)*2;
731 for (
int index =0; index < size && !isMultiLine; ++index )
733 writeValue( value[index] );
734 lineLength += int( childValues_[index].length() );
735 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
737 addChildValues_ =
false;
738 isMultiLine = isMultiLine || lineLength >= rightMargin_;
745 StyledStreamWriter::pushValue(
const std::string &value )
747 if ( addChildValues_ )
748 childValues_.push_back( value );
755 StyledStreamWriter::writeIndent()
769 *document_ <<
'\n' << indentString_;
774 StyledStreamWriter::writeWithIndent(
const std::string &value )
782 StyledStreamWriter::indent()
784 indentString_ += indentation_;
789 StyledStreamWriter::unindent()
791 assert( indentString_.size() >= indentation_.size() );
792 indentString_.resize( indentString_.size() - indentation_.size() );
797 StyledStreamWriter::writeCommentBeforeValue(
const Value &root )
801 *document_ << normalizeEOL( root.getComment(
commentBefore ) );
807 StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value &root )
815 *document_ << normalizeEOL( root.getComment(
commentAfter ) );
822 StyledStreamWriter::hasCommentForValue(
const Value &value )
831 StyledStreamWriter::normalizeEOL(
const std::string &text )
833 std::string normalized;
834 normalized.reserve( text.length() );
835 const char *begin = text.c_str();
836 const char *end = begin + text.length();
837 const char *current = begin;
838 while ( current != end )
843 if ( *current ==
'\n' )
857 writer.
write(sout, root);
std::ostream & operator<<(std::ostream &sout, const Value &root)
Output using the StyledStreamWriter.
Writes a Value in JSON format in a human friendly way, to a stream rather than to a string...
virtual std::string write(const Value &root)
Serialize a Value in JSON format.
a comment placed on the line before a value
object value (collection of name/value pairs).
JSON (JavaScript Object Notation).
a comment just after a value on the same line
a comment on the line after a value (only make sense for root value)
void write(std::ostream &out, const Value &root)
Serialize a Value in JSON format.
Members getMemberNames() const
Return a list of the member names.
array value (ordered list)