Skip to content

Commit 6fa6e69

Browse files
committed
added json writer
1 parent abfa9ce commit 6fa6e69

File tree

7 files changed

+342
-1
lines changed

7 files changed

+342
-1
lines changed

libgrive/src/json/Val.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
#include "Val.hh"
22+
#include "ValVisitor.hh"
2223

2324
#include <iostream>
2425

@@ -132,6 +133,45 @@ void Val::Add( const std::string& key, const Val& value )
132133
As<Object>().insert( std::make_pair(key, value) ) ;
133134
}
134135

136+
void Val::Visit( ValVisitor *visitor ) const
137+
{
138+
switch ( Type() )
139+
{
140+
case null_type: visitor->VisitNull() ; break ;
141+
case int_type: visitor->Visit( As<long long>() ) ; break ;
142+
case double_type: visitor->Visit( As<double>() ) ; break ;
143+
case string_type: visitor->Visit( As<std::string>() ) ; break ;
144+
case bool_type: visitor->Visit( As<bool>() ) ; break ;
145+
146+
case object_type:
147+
{
148+
visitor->StartObject() ;
149+
150+
const Object& obj = As<Object>() ;
151+
for ( Object::const_iterator i = obj.begin() ; i != obj.end() ; ++i )
152+
{
153+
visitor->VisitKey( i->first ) ;
154+
i->second.Visit( visitor ) ;
155+
}
156+
157+
visitor->EndObject() ;
158+
break ;
159+
}
160+
161+
case array_type:
162+
{
163+
visitor->StartArray() ;
164+
165+
const Array& arr = As<Array>() ;
166+
for ( Array::const_iterator i = arr.begin() ; i != arr.end() ; ++i )
167+
i->Visit( visitor ) ;
168+
169+
visitor->EndArray() ;
170+
break ;
171+
}
172+
}
173+
}
174+
135175
} // end of namespace
136176

137177
namespace std

libgrive/src/json/Val.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public :
112112
bool FindInArray( const std::string& key, const std::string& value, Val& result ) const ;
113113

114114
// friend std::ostream& operator<<( std::ostream& os, const Val& json ) ;
115-
// void Visit( DataStream *out ) const ;
115+
void Visit( ValVisitor *visitor ) const ;
116116

117117
private :
118118
struct Base ;

libgrive/src/json/ValWriter.cc

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
grive: an GPL program to sync a local directory with Google Drive
3+
Copyright (C) 2013 Wan Wai Ho
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License
7+
as published by the Free Software Foundation version 2
8+
of the License.
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, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18+
MA 02110-1301, USA.
19+
*/
20+
21+
#include "ValWriter.hh"
22+
#include "util/DataStream.hh"
23+
24+
#include <yajl/yajl_gen.h>
25+
26+
#include <cassert>
27+
28+
namespace gr {
29+
30+
struct ValWriter::Impl
31+
{
32+
yajl_gen gen ;
33+
DataStream *out ;
34+
} ;
35+
36+
ValWriter::ValWriter( DataStream *out ) :
37+
m_impl( new Impl )
38+
{
39+
assert( out != 0 ) ;
40+
41+
m_impl->out = out ;
42+
m_impl->gen = yajl_gen_alloc(0) ;
43+
yajl_gen_config( m_impl->gen, yajl_gen_print_callback, &ValWriter::WriteCallback, this ) ;
44+
}
45+
46+
ValWriter::~ValWriter()
47+
{
48+
yajl_gen_free( m_impl->gen ) ;
49+
}
50+
51+
void ValWriter::Visit( long long t )
52+
{
53+
yajl_gen_integer( m_impl->gen, t ) ;
54+
}
55+
56+
void ValWriter::Visit( double t )
57+
{
58+
yajl_gen_double( m_impl->gen, t ) ;
59+
}
60+
61+
void ValWriter::Visit( const std::string& t )
62+
{
63+
yajl_gen_string( m_impl->gen,
64+
reinterpret_cast<const unsigned char*>(t.c_str()), t.size() ) ;
65+
}
66+
67+
void ValWriter::Visit( bool t )
68+
{
69+
yajl_gen_bool( m_impl->gen, t ) ;
70+
}
71+
72+
void ValWriter::VisitNull()
73+
{
74+
yajl_gen_null( m_impl->gen ) ;
75+
}
76+
77+
void ValWriter::StartArray()
78+
{
79+
yajl_gen_array_open( m_impl->gen ) ;
80+
}
81+
82+
void ValWriter::EndArray()
83+
{
84+
yajl_gen_array_close( m_impl->gen ) ;
85+
}
86+
87+
void ValWriter::StartObject()
88+
{
89+
yajl_gen_map_open( m_impl->gen ) ;
90+
}
91+
92+
void ValWriter::VisitKey( const std::string& t )
93+
{
94+
Visit(t) ;
95+
}
96+
97+
void ValWriter::EndObject()
98+
{
99+
yajl_gen_map_close( m_impl->gen ) ;
100+
}
101+
102+
void ValWriter::WriteCallback( void *ctx, const char *str, std::size_t size )
103+
{
104+
ValWriter *pthis = reinterpret_cast<ValWriter*>(ctx) ;
105+
assert( pthis != 0 ) ;
106+
assert( pthis->m_impl->out != 0 ) ;
107+
108+
pthis->m_impl->out->Write( str, size ) ;
109+
}
110+
111+
} // end of namespace

libgrive/src/json/ValWriter.hh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
grive: an GPL program to sync a local directory with Google Drive
3+
Copyright (C) 2013 Wan Wai Ho
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License
7+
as published by the Free Software Foundation version 2
8+
of the License.
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, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18+
MA 02110-1301, USA.
19+
*/
20+
21+
#pragma once
22+
23+
#include "ValVisitor.hh"
24+
#include <memory>
25+
26+
namespace gr {
27+
28+
class DataStream ;
29+
30+
class ValWriter : public ValVisitor
31+
{
32+
public :
33+
ValWriter( DataStream *out ) ;
34+
~ValWriter() ;
35+
36+
void Visit( long long t ) ;
37+
void Visit( double t ) ;
38+
void Visit( const std::string& t ) ;
39+
void Visit( bool t ) ;
40+
void VisitNull() ;
41+
42+
void StartArray() ;
43+
void EndArray() ;
44+
void StartObject() ;
45+
void VisitKey( const std::string& t ) ;
46+
void EndObject() ;
47+
48+
private :
49+
static void WriteCallback( void *ctx, const char *str, std::size_t size ) ;
50+
51+
private :
52+
struct Impl ;
53+
std::auto_ptr<Impl> m_impl ;
54+
} ;
55+
56+
} // end of namespace
57+

libgrive/src/util/StringStream.cc

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
webwrite: an GPL program to sync a local directory with Google Drive
3+
Copyright (C) 2012 Wan Wai Ho
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License
7+
as published by the Free Software Foundation version 2
8+
of the License.
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, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18+
*/
19+
20+
#include "StringStream.hh"
21+
22+
#include <algorithm>
23+
24+
namespace gr {
25+
26+
namespace
27+
{
28+
// the max size of the cached string. this is to prevent allocating
29+
// too much memory if client sends a line too long (i.e. DOS attack)
30+
const std::size_t capacity = 1024 ;
31+
}
32+
33+
StringStream::StringStream( const std::string& init ) :
34+
m_str( init )
35+
{
36+
}
37+
38+
/// Read `size` bytes from the stream. Those bytes will be removed from
39+
/// the underlying string by calling `std::string::erase()`. Therefore, it is
40+
/// not a good idea to call Read() to read byte-by-byte.
41+
std::size_t StringStream::Read( char *data, std::size_t size )
42+
{
43+
// wow! no need to count count == 0
44+
std::size_t count = std::min( m_str.size(), size ) ;
45+
std::copy( m_str.begin(), m_str.begin() + count, data ) ;
46+
m_str.erase( 0, count ) ;
47+
return count ;
48+
}
49+
50+
std::size_t StringStream::Write( const char *data, std::size_t size )
51+
{
52+
std::size_t count = std::min( size, capacity - m_str.size() ) ;
53+
m_str.insert( m_str.end(), data, data+count ) ;
54+
return count ;
55+
}
56+
57+
const std::string& StringStream::Str() const
58+
{
59+
return m_str ;
60+
}
61+
62+
void StringStream::Str( const std::string& str )
63+
{
64+
m_str = str ;
65+
}
66+
67+
} // end of namespace

libgrive/src/util/StringStream.hh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
webwrite: an GPL program to sync a local directory with Google Drive
3+
Copyright (C) 2012 Wan Wai Ho
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License
7+
as published by the Free Software Foundation version 2
8+
of the License.
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, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18+
*/
19+
20+
#pragma once
21+
22+
#include "DataStream.hh"
23+
24+
#include <string>
25+
26+
namespace gr {
27+
28+
/** \brief DataStream base on `std::string`s
29+
30+
StringStream is a DataStream back-end that uses std::string for storage.
31+
It is useful for unit tests and text parsing, especially when used with
32+
StreamParser.
33+
34+
StringStream has a limit on the maximum number of byte it stores. This
35+
is to prevent DOS attacks in which the client sends a lot of bytes before
36+
the delimiter (e.g. new-line characters) and the server is forced to hold
37+
all of them in memory.
38+
39+
The limit is current 1024 bytes.
40+
*/
41+
class StringStream : public DataStream
42+
{
43+
public :
44+
explicit StringStream( const std::string& init = std::string() ) ;
45+
46+
std::size_t Read( char *data, std::size_t size ) ;
47+
std::size_t Write( const char *data, std::size_t size ) ;
48+
49+
const std::string& Str() const ;
50+
void Str( const std::string& str ) ;
51+
52+
private :
53+
std::string m_str ;
54+
} ;
55+
56+
} // end of namespace

libgrive/test/btest/JsonValTest.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "json/JsonParser.hh"
2121
#include "json/Val.hh"
2222
#include "json/ValBuilder.hh"
23+
#include "json/ValWriter.hh"
24+
#include "util/StringStream.hh"
2325

2426
#include <boost/test/unit_test.hpp>
2527

@@ -42,6 +44,14 @@ BOOST_AUTO_TEST_CASE( Test )
4244

4345
BOOST_CHECK( json.Is<Val::Object>() ) ;
4446
BOOST_CHECK_EQUAL( json["key"].As<long long>(), 100 ) ;
47+
48+
StringStream ss ;
49+
ValWriter wr( &ss ) ;
50+
json.Visit( &wr ) ;
51+
52+
BOOST_CHECK_EQUAL( ss.Str(), "{\"key\":100}" ) ;
53+
54+
// std::cout << ss.Str() << std::endl ;
4555
}
4656

4757
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)