コード例 #1
0
static void format_collection( JsonIn &jsin, JsonOut &jsout, int depth,
                               std::function<void(JsonIn &, JsonOut &, int, bool )>write_func )
{
    if( depth > 1 ) {
        // We're backtracking by storing jsin and jsout state before formatting
        // and restoring it afterwards if necessary.
        int in_start_pos = jsin.tell();
        bool ate_seperator = jsin.get_ate_separator();
        int out_start_pos = jsout.tell();
        bool need_separator = jsout.get_need_separator();
        write_func( jsin, jsout, depth, false );
        if( jsout.tell() - out_start_pos <= 120 ) {
            // Line is short enough, so we're done.
            return;
        } else {
            // Reset jsin and jsout to their initial state,
            // and we'll serialize while forcing wrapping.
            jsin.seek( in_start_pos );
            jsin.set_ate_separator( ate_seperator );
            jsout.seek( out_start_pos );
            if( need_separator ) {
                jsout.set_need_separator();
            }
        }
    }
    write_func( jsin, jsout, depth, true );
}
コード例 #2
0
static void format( JsonIn &jsin, JsonOut &jsout, int depth )
{
    depth++;
    if( jsin.test_array() ) {
        format_collection( jsin, jsout, depth, write_array );
    } else if( jsin.test_object() ) {
        format_collection( jsin, jsout, depth, write_object );
    } else if( jsin.test_string() ) {
        std::string str = jsin.get_string();
        jsout.write( str );
    } else if( jsin.test_number() ) {
        // Have to introspect into the string to distinguish integers from floats.
        // Otherwise they won't serialize correctly.
        const int start_pos = jsin.tell();
        double num = jsin.get_float();
        const int end_pos = jsin.tell();
        std::string str_form = jsin.substr( start_pos, end_pos - start_pos );
        if( str_form.find( '.' ) == std::string::npos ) {
            jsout.write( static_cast<long>( num ) );
        } else {
            // This is QUITE insane, but as far as I can tell there is NO way to configure
            // an ostream to output a float/double meeting two constraints:
            // Always emit a decimal point (and single trailing 0 after a bare decimal point).
            // Don't emit trailing zeroes otherwise.
            std::string double_str = std::to_string( num );
            double_str.erase( double_str.find_last_not_of( '0' ) + 1, std::string::npos );
            if( double_str.back() == '.' ) {
                double_str += "0";
            }
            jsout.write_separator();
            *jsout.get_stream() << double_str;
            jsout.set_need_separator();
        }
        jsin.seek( end_pos );
    } else if( jsin.test_bool() ) {
        bool tf = jsin.get_bool();
        jsout.write( tf );
    } else if( jsin.test_null() ) {
        jsout.write_null();
    } else {
        std::cerr << "Encountered unrecognized json element \"";
        const int start_pos = jsin.tell();
        jsin.skip_value();
        const int end_pos = jsin.tell();
        for( int i = start_pos; i < end_pos; ++i ) {
            jsin.seek( i );
            std::cerr << jsin.peek();
        }
        std::cerr << "\"" << std::endl;
    }
}