pretty example

This commit is contained in:
Vinnie Falco 2019-11-15 20:11:57 -08:00
parent cf95fc7c29
commit 2db5a6c57f
4 changed files with 222 additions and 78 deletions

View File

@ -10,11 +10,13 @@
GroupSources(example "/")
add_executable (pretty
file.hpp
pretty.cpp
)
set_property(TARGET pretty PROPERTY FOLDER "example")
add_executable (allocator
file.hpp
allocator.cpp
)
set_property(TARGET allocator PROPERTY FOLDER "example")

111
example/file.hpp Normal file
View File

@ -0,0 +1,111 @@
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/vinniefalco/json
//
#ifndef BOOST_JSON_EXAMPLE_FILE_HPP
#define BOOST_JSON_EXAMPLE_FILE_HPP
#include <boost/json/config.hpp>
#include <cstdio>
class file
{
FILE* f_ = nullptr;
public:
~file()
{
if(f_)
std::fclose(f_);
}
file() = default;
file( file&& other ) noexcept
: f_(other.f_)
{
other.f_ = nullptr;
}
file( char const* path, char const* mode )
{
open( path, mode );
}
file&
operator=(file&& other) noexcept
{
close();
f_ = other.f_;
other.f_ = nullptr;
return *this;
}
void
close()
{
if(f_)
{
std::fclose(f_);
f_ = nullptr;
}
}
void
open(
char const* path,
char const* mode,
boost::json::error_code& ec)
{
close();
f_ = std::fopen( path, mode );
if( ! f_ )
{
ec.assign( errno, boost::json::generic_category() );
return;
}
}
void
open(
char const* path,
char const* mode)
{
boost::json::error_code ec;
open(path, mode, ec);
if(ec)
throw boost::json::system_error(ec);
}
bool
eof() const noexcept
{
return std::feof( f_ ) != 0;
}
std::size_t
read( char* data, std::size_t size, boost::json::error_code& ec)
{
auto const nread = std::fread( data, 1, size, f_ );
if( std::ferror(f_) )
ec.assign( errno, boost::json::generic_category() );
return nread;
}
std::size_t
read( char* data, std::size_t size )
{
boost::json::error_code ec;
auto const nread = read( data, size, ec );
if(ec)
throw boost::json::system_error(ec);
return nread;
}
};
#endif

View File

@ -13,96 +13,115 @@
*/
#include <boost/json.hpp>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include "file.hpp"
namespace json = boost::json;
class file
{
FILE* f_ = nullptr;
public:
~file()
{
if(f_)
std::fclose(f_);
}
file() = default;
void
close()
{
if(f_)
{
std::fclose(f_);
f_ = nullptr;
}
}
void
open(
char const* path,
char const* mode,
json::error_code& ec)
{
close();
f_ = std::fopen( path, mode );
if( ! f_ )
{
ec.assign( errno, json::generic_category() );
return;
}
}
};
json::value
parse_file( char const* filename )
{
json::error_code ec;
auto f = std::fopen( filename, "r" );
if( ! f )
{
ec.assign( errno, json::generic_category() );
throw json::system_error(ec);
}
file f( filename, "r" );
json::parser p;
p.start();
do
{
char buf[4096];
// Read from the file into our buffer.
auto const nread = fread( buf, 1, sizeof(buf), f );
if( std::ferror(f) )
{
ec.assign( errno, json::generic_category() );
throw json::system_error(ec);
}
auto nparsed = p.write_some( buf, nread, ec);
// Make sure we use all the characters in the file.
if( ! ec && nparsed < nread )
nparsed = p.write_some( buf + nparsed, sizeof(buf) - nparsed, ec );
if( ec )
throw json::system_error(ec);
auto const nread = f.read( buf, sizeof(buf) );
p.write( buf, nread );
}
while( ! std::feof(f) );
// Tell the parser there is no more serialized JSON.
p.finish(ec);
if( ec )
throw json::system_error(ec);
while( ! f.eof() );
p.finish();
return p.release();
}
void
pretty_print( std::ostream& os, json::value const& jv )
pretty_print( std::ostream& os, json::value const& jv, std::string* indent = nullptr )
{
std::string indent_;
if(! indent)
indent = &indent_;
switch(jv.kind())
{
case json::kind::object:
{
os << "{\n";
indent->append(4, ' ');
auto const& obj = jv.get_object();
if(! obj.empty())
{
auto it = obj.begin();
goto loop_obj;
while( ++it != obj.end() )
{
os << ",\n";
loop_obj:
os << *indent << json::to_string(it->key()) << " : ";
pretty_print( os, it->value(), indent);
}
}
os << "\n";
indent->resize(indent->size() - 4);
os << *indent << "}";
break;
}
case json::kind::array:
{
os << "[\n";
indent->append(4, ' ');
auto const& arr = jv.get_array();
if(! arr.empty())
{
auto it = arr.begin();
goto loop_arr;
while( ++it != arr.end() )
{
os << ",\n";
loop_arr:
os << *indent;
pretty_print( os, *it, indent);
}
}
os << "\n";
indent->resize(indent->size() - 4);
os << *indent << "]";
break;
}
case json::kind::string:
{
os << json::to_string(jv.get_string());
break;
}
case json::kind::uint64:
os << jv.get_uint64();
break;
case json::kind::int64:
os << jv.get_int64();
break;
case json::kind::double_:
os << jv.get_double();
break;
case json::kind::bool_:
if(jv.get_bool())
os << "true";
else
os << "false";
break;
case json::kind::null:
os << "null";
break;
}
if(indent->empty())
os << "\n";
}
int

View File

@ -63,7 +63,7 @@ enum class basic_parser::state : char
esc1, esc2, esc3, esc4,
sur1, sur2, sur3,
num,
lit,
litt, litf, litn
};
//----------------------------------------------------------
@ -244,7 +244,7 @@ loop_val:
++p;
lit_ = "rue";
ev_ = error::expected_true;
*st_ = state::lit;
*st_ = state::litt;
goto loop;
// false
@ -269,7 +269,7 @@ loop_val:
++p;
lit_ = "alse";
ev_ = error::expected_false;
*st_ = state::lit;
*st_ = state::litf;
goto loop;
// null
@ -293,7 +293,7 @@ loop_val:
++p;
lit_ = "ull";
ev_ = error::expected_null;
*st_ = state::lit;
*st_ = state::litn;
goto loop;
default:
@ -829,7 +829,9 @@ loop_num:
// string literal (true, false, null)
case state::lit:
case state::litt:
case state::litf:
case state::litn:
BOOST_JSON_ASSERT(lit_ != nullptr);
while(p < p1)
{
@ -841,6 +843,14 @@ loop_num:
++p;
if(*++lit_ == 0)
{
if(*st_ == state::litt)
this->on_bool(true, ec);
else if(*st_ == state::litf)
this->on_bool(false, ec);
else
this->on_null(ec);
if(ec)
goto yield;
st_.pop();
goto loop;
}
@ -980,7 +990,9 @@ finish(error_code& ec)
break;
}
case state::lit:
case state::litt:
case state::litf:
case state::litn:
ec = ev_;
return;