From 755ee1c9adfe290f68e18ddea0b01673186b3917 Mon Sep 17 00:00:00 2001 From: Nestal Wan Date: Sun, 28 Apr 2013 18:40:21 +0800 Subject: [PATCH] new qt gui --- CMakeLists.txt | 2 + bgrive/CMakeLists.txt | 43 ++++ bgrive/src/MainWnd.cc | 30 +++ bgrive/src/MainWnd.hh | 40 ++++ bgrive/src/main.cc | 78 ++++++ bgrive/ui/MainWindow.ui | 86 +++++++ libgrive/src/drive/Feed.hh | 2 +- libgrive/src/drive/Resource.cc | 6 +- libgrive/src/drive/State.cc | 6 +- libgrive/src/http/Agent.hh | 6 +- libgrive/src/http/CurlAgent.cc | 8 +- libgrive/src/http/CurlAgent.hh | 2 +- libgrive/src/http/Download.cc | 2 +- libgrive/src/http/Download.hh | 4 +- libgrive/src/http/MarshalAgent.hh | 39 +++ libgrive/src/http/Receivable.hh | 1 + libgrive/src/protocol/AuthAgent.cc | 2 +- libgrive/src/protocol/AuthAgent.hh | 2 +- libgrive/src/protocol/Json.cc | 250 ++++++++++++++++---- libgrive/src/protocol/Json.hh | 49 +++- libgrive/src/util/Config.cc | 11 +- libgrive/src/util/Config.hh | 2 +- libgrive/src/util/Crypt.cc | 8 +- libgrive/src/util/Crypt.hh | 4 +- libgrive/src/util/DataStream.hh | 55 +++++ libgrive/src/util/Exception.cc | 11 +- libgrive/src/util/Exception.hh | 43 +--- libgrive/src/util/{StdioFile.cc => File.cc} | 107 ++++++--- libgrive/src/util/{StdioFile.hh => File.hh} | 33 ++- libgrive/src/util/FileSystem.hh | 13 - libgrive/src/util/MemMap.cc | 6 +- libgrive/src/util/MemMap.hh | 4 +- 32 files changed, 778 insertions(+), 177 deletions(-) create mode 100644 bgrive/CMakeLists.txt create mode 100644 bgrive/src/MainWnd.cc create mode 100644 bgrive/src/MainWnd.hh create mode 100644 bgrive/src/main.cc create mode 100644 bgrive/ui/MainWindow.ui create mode 100644 libgrive/src/http/MarshalAgent.hh create mode 100644 libgrive/src/util/DataStream.hh rename libgrive/src/util/{StdioFile.cc => File.cc} (63%) rename libgrive/src/util/{StdioFile.hh => File.hh} (66%) diff --git a/CMakeLists.txt b/CMakeLists.txt index def7ca0..7d16f2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ set( GRIVE_VERSION "0.3.0-pre" ) # common compile options add_definitions( -DVERSION="${GRIVE_VERSION}" ) add_definitions( -D_FILE_OFFSET_BITS=64 ) +add_definitions( -DPROJ_NS=gr ) add_subdirectory( libgrive ) add_subdirectory( grive ) +add_subdirectory( bgrive ) diff --git a/bgrive/CMakeLists.txt b/bgrive/CMakeLists.txt new file mode 100644 index 0000000..074ab38 --- /dev/null +++ b/bgrive/CMakeLists.txt @@ -0,0 +1,43 @@ +project( bgrive ) + +find_package(Qt4 REQUIRED) +find_package(Boost REQUIRED) +INCLUDE(${QT_USE_FILE}) + +include_directories( + ${bgrive_SOURCE_DIR}/../libgrive/src + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +file (GLOB BGRIVE_EXE_SRC + ${bgrive_SOURCE_DIR}/src/*.cc +) + +file (GLOB BGRIVE_UI + ${bgrive_SOURCE_DIR}/ui/*.ui +) + +QT4_WRAP_UI(BGRIVE_UI_SRCS ${BGRIVE_UI}) +QT4_WRAP_CPP(BGRIVE_MOC_SRCS + src/MainWnd.hh ) + +add_executable( bgrive_executable + ${BGRIVE_EXE_SRC} + ${BGRIVE_UI_SRCS} + ${BGRIVE_MOC_SRCS} +) + +target_link_libraries( bgrive_executable + ${Boost_LIBRARIES} + ${QT_QTMAIN_LIBRARY} + ${QT_LIBRARIES} + grive +) + +set_target_properties( bgrive_executable + PROPERTIES OUTPUT_NAME bgrive +) + +install(TARGETS bgrive_executable RUNTIME DESTINATION bin) +install(FILES doc/grive.1 DESTINATION share/man/man1 ) diff --git a/bgrive/src/MainWnd.cc b/bgrive/src/MainWnd.cc new file mode 100644 index 0000000..1712ebc --- /dev/null +++ b/bgrive/src/MainWnd.cc @@ -0,0 +1,30 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2013 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ + +#include "MainWnd.hh" + +namespace gr { + +MainWnd::MainWnd( ) +{ + m_ui.setupUi(this) ; +} + +} // end of namespace diff --git a/bgrive/src/MainWnd.hh b/bgrive/src/MainWnd.hh new file mode 100644 index 0000000..f50d431 --- /dev/null +++ b/bgrive/src/MainWnd.hh @@ -0,0 +1,40 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2013 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ + +#pragma once + +#include +#include "ui_MainWindow.h" + +namespace gr { + +class MainWnd : public QMainWindow +{ + Q_OBJECT + +public : + MainWnd( ) ; + +private : + Ui::MainWindow m_ui ; +} ; + +} // end of namespace + diff --git a/bgrive/src/main.cc b/bgrive/src/main.cc new file mode 100644 index 0000000..4b61317 --- /dev/null +++ b/bgrive/src/main.cc @@ -0,0 +1,78 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2013 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. +*/ + +#include "MainWnd.hh" + +#include +#include + +#include "drive/CommonUri.hh" +#include "drive/Entry.hh" +#include "drive/Feed.hh" + +#include "http/CurlAgent.hh" +#include "http/Header.hh" +#include "http/XmlResponse.hh" + +#include "protocol/Json.hh" +#include "protocol/OAuth2.hh" +#include "protocol/AuthAgent.hh" + +#include "util/File.hh" + +#include + +const std::string client_id = "22314510474.apps.googleusercontent.com" ; +const std::string client_secret = "bl4ufi89h-9MkFlypcI7R785" ; + +using namespace gr ; + +int main( int argc, char **argv ) +{ + File file( ".grive" ) ; + Json cfg = Json::Parse( &file ) ; + + std::string refresh_token = cfg["refresh_token"].Str() ; + qDebug() << refresh_token.c_str() ; + + OAuth2 token( refresh_token, client_id, client_secret ) ; + AuthAgent agent( token, std::auto_ptr( new http::CurlAgent ) ) ; + + + http::XmlResponse xml ; + agent.Get( feed_base + "/-/folder?max-results=50&showroot=true", &xml, http::Header() ) ; + + Feed feed( xml.Response() ) ; + do + { + // first, get all collections from the query result + for ( Feed::iterator i = feed.begin() ; i != feed.end() ; ++i ) + { + Entry e( *i ) ; + qDebug() << e.Name().c_str() ; + } + } while ( feed.GetNext( &agent, http::Header() ) ) ; + + QApplication app( argc, argv ) ; + MainWnd wnd ; + wnd.show(); + + return app.exec() ; +} diff --git a/bgrive/ui/MainWindow.ui b/bgrive/ui/MainWindow.ui new file mode 100644 index 0000000..e69c600 --- /dev/null +++ b/bgrive/ui/MainWindow.ui @@ -0,0 +1,86 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + Grive + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + + + 1 + 0 + + + + + + + + + + + 0 + 0 + 800 + 23 + + + + + &File + + + + + + + + + E&xit + + + + + + + m_action_exit + activated() + MainWindow + close() + + + -1 + -1 + + + 399 + 299 + + + + + diff --git a/libgrive/src/drive/Feed.hh b/libgrive/src/drive/Feed.hh index f41fb7d..deaf18c 100644 --- a/libgrive/src/drive/Feed.hh +++ b/libgrive/src/drive/Feed.hh @@ -67,7 +67,7 @@ private : std::auto_ptr m_log ; xml::Node m_root ; - xml::NodeSet m_entries ; + xml::NodeSet m_entries ; } ; class Feed::iterator : public boost::iterator_adaptor< diff --git a/libgrive/src/drive/Resource.cc b/libgrive/src/drive/Resource.cc index e64bd0f..63a54bd 100644 --- a/libgrive/src/drive/Resource.cc +++ b/libgrive/src/drive/Resource.cc @@ -32,7 +32,7 @@ #include "util/Crypt.hh" #include "util/log/Log.hh" #include "util/OS.hh" -#include "util/StdioFile.hh" +#include "util/File.hh" #include "xml/Node.hh" #include "xml/NodeSet.hh" #include "xml/String.hh" @@ -269,7 +269,7 @@ void Resource::FromLocal( const DateTime& last_sync ) else m_state = ( m_mtime > last_sync ? local_new : remote_deleted ) ; - m_name = Path2Str( path.filename() ) ; + m_name = path.filename().string() ; m_kind = fs::is_directory(path) ? "folder" : "file" ; m_md5 = fs::is_directory(path) ? "" : crypt::MD5::Get( path ) ; } @@ -583,7 +583,7 @@ bool Resource::Upload( { assert( http != 0 ) ; - StdioFile file( Path() ) ; + File file( Path() ) ; std::ostringstream xcontent_len ; xcontent_len << "X-Upload-Content-Length: " << file.Size() ; diff --git a/libgrive/src/drive/State.cc b/libgrive/src/drive/State.cc index 43e6367..195e696 100644 --- a/libgrive/src/drive/State.cc +++ b/libgrive/src/drive/State.cc @@ -25,6 +25,7 @@ #include "http/Agent.hh" #include "util/Crypt.hh" +#include "util/File.hh" #include "util/log/Log.hh" #include "protocol/Json.hh" @@ -72,7 +73,7 @@ void State::FromLocal( const fs::path& p, gr::Resource* folder ) for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i ) { - std::string fname = Path2Str(i->path().filename()) ; + std::string fname = i->path().filename().string() ; if ( IsIgnore(fname) ) Log( "file %1% is ignored by grive", fname, log::verbose ) ; @@ -228,7 +229,8 @@ void State::Read( const fs::path& filename ) { try { - Json json = Json::ParseFile( filename.string() ) ; + File file( filename ) ; + Json json = Json::Parse( &file ) ; Json last_sync = json["last_sync"] ; m_last_sync.Assign( diff --git a/libgrive/src/http/Agent.hh b/libgrive/src/http/Agent.hh index 0baa032..0ca1e9b 100644 --- a/libgrive/src/http/Agent.hh +++ b/libgrive/src/http/Agent.hh @@ -23,7 +23,7 @@ namespace gr { -class StdioFile ; +class File ; namespace http { @@ -33,6 +33,8 @@ class Receivable ; class Agent { public : + virtual ~Agent() {} + virtual long Put( const std::string& url, const std::string& data, @@ -41,7 +43,7 @@ public : virtual long Put( const std::string& url, - StdioFile& file, + File& file, Receivable *dest, const Header& hdr ) = 0 ; diff --git a/libgrive/src/http/CurlAgent.cc b/libgrive/src/http/CurlAgent.cc index 09bedee..2cf78b8 100644 --- a/libgrive/src/http/CurlAgent.cc +++ b/libgrive/src/http/CurlAgent.cc @@ -25,7 +25,7 @@ #include "Receivable.hh" #include "util/log/Log.hh" -#include "util/StdioFile.hh" +#include "util/File.hh" #include @@ -62,7 +62,7 @@ size_t ReadStringCallback( void *ptr, std::size_t size, std::size_t nmemb, std:: return count ; } -size_t ReadFileCallback( void *ptr, std::size_t size, std::size_t nmemb, StdioFile *file ) +size_t ReadFileCallback( void *ptr, std::size_t size, std::size_t nmemb, File *file ) { assert( ptr != 0 ) ; assert( file != 0 ) ; @@ -73,7 +73,7 @@ size_t ReadFileCallback( void *ptr, std::size_t size, std::size_t nmemb, StdioFi assert( count <= std::numeric_limits::max() ) ; if ( count > 0 ) - file->Read( ptr, static_cast(count) ) ; + file->Read( static_cast(ptr), static_cast(count) ) ; return count ; } @@ -197,7 +197,7 @@ long CurlAgent::Put( long CurlAgent::Put( const std::string& url, - StdioFile& file, + File& file, Receivable *dest, const Header& hdr ) { diff --git a/libgrive/src/http/CurlAgent.hh b/libgrive/src/http/CurlAgent.hh index 9db1d23..2b9a394 100644 --- a/libgrive/src/http/CurlAgent.hh +++ b/libgrive/src/http/CurlAgent.hh @@ -47,7 +47,7 @@ public : long Put( const std::string& url, - StdioFile& file, + File& file, Receivable *dest, const Header& hdr ) ; diff --git a/libgrive/src/http/Download.cc b/libgrive/src/http/Download.cc index 15171cd..3b98ac4 100644 --- a/libgrive/src/http/Download.cc +++ b/libgrive/src/http/Download.cc @@ -72,7 +72,7 @@ std::size_t Download::OnData( void *data, std::size_t count ) if ( m_crypt.get() != 0 ) m_crypt->Write( data, count ) ; - return m_file.Write( data, count ) ; + return m_file.Write( static_cast(data), count ) ; } } } // end of namespace diff --git a/libgrive/src/http/Download.hh b/libgrive/src/http/Download.hh index d3bdc59..683f864 100644 --- a/libgrive/src/http/Download.hh +++ b/libgrive/src/http/Download.hh @@ -20,7 +20,7 @@ #pragma once #include "Receivable.hh" -#include "util/StdioFile.hh" +#include "util/File.hh" #include @@ -47,7 +47,7 @@ public : std::size_t OnData( void *data, std::size_t count ) ; private : - StdioFile m_file ; + File m_file ; std::auto_ptr m_crypt ; } ; diff --git a/libgrive/src/http/MarshalAgent.hh b/libgrive/src/http/MarshalAgent.hh new file mode 100644 index 0000000..0ca2b27 --- /dev/null +++ b/libgrive/src/http/MarshalAgent.hh @@ -0,0 +1,39 @@ +/* + grive: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "http/Agent.hh" + +namespace gr { namespace http { + +class HttpRequest ; + +/*! \brief An marshaller for HTTP agent + + This agent will marshal the HTTP requests to a request objects containing the arguments + of the request and the response. +*/ +class MarshalAgent : public Agent +{ +public : + MarshalAgent( std::auto_ptr real_agent ) ; +} ; + +}} // end of namespace diff --git a/libgrive/src/http/Receivable.hh b/libgrive/src/http/Receivable.hh index 2982aa1..0eb1afb 100644 --- a/libgrive/src/http/Receivable.hh +++ b/libgrive/src/http/Receivable.hh @@ -26,6 +26,7 @@ namespace gr { namespace http { class Receivable { public : + virtual ~Receivable() {} virtual std::size_t OnData( void *data, std::size_t count ) = 0 ; virtual void Clear() = 0 ; } ; diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 9d0239b..c3cdabb 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -62,7 +62,7 @@ long AuthAgent::Put( long AuthAgent::Put( const std::string& url, - StdioFile& file, + File& file, Receivable *dest, const Header& hdr ) { diff --git a/libgrive/src/protocol/AuthAgent.hh b/libgrive/src/protocol/AuthAgent.hh index 58900d1..fe6ae22 100644 --- a/libgrive/src/protocol/AuthAgent.hh +++ b/libgrive/src/protocol/AuthAgent.hh @@ -44,7 +44,7 @@ public : long Put( const std::string& url, - StdioFile& file, + File& file, http::Receivable *dest, const http::Header& hdr ) ; diff --git a/libgrive/src/protocol/Json.cc b/libgrive/src/protocol/Json.cc index 7012db7..58da219 100644 --- a/libgrive/src/protocol/Json.cc +++ b/libgrive/src/protocol/Json.cc @@ -19,10 +19,21 @@ #include "Json.hh" -#include "util/StdioFile.hh" +#include "util/DataStream.hh" +// needs to include stdint.h before json-c to avoid macro re-def warning +#include + +// disable macro re-def warning for json-c headers +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4005) +#endif #include #include +#ifdef _MSC_VER + #pragma warning(pop) +#endif #include #include @@ -35,51 +46,99 @@ Json::Json( ) : m_json( ::json_object_new_object() ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json object" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_object" ) + ) ; } Json::Json( const char *str ) : m_json( ::json_object_new_string( str ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( - Error() << expt::ErrMsg( "cannot create json string \"" + std::string(str) + "\"" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_string" ) + << ValueErr( str ) + ) ; +} + +struct json_object* Json::InitStr( const char *str, std::size_t n ) +{ + struct json_object *j = ::json_object_new_string_len( str, n ) ; + if ( j == 0 ) + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_string_len" ) + << ValueErr( std::string(str, n) ) + ) ; + return j ; } template <> Json::Json( const std::string& str ) : - m_json( ::json_object_new_string( str.c_str() ) ) + m_json( InitStr( str.c_str(), str.size() ) ) { - if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( - Error() << expt::ErrMsg( "cannot create json string \"" + str + "\"" ) ) ; - - // paranoid check - assert( ::json_object_get_string( m_json ) == str ) ; } template <> -Json::Json( const int& l ) : +Json::Json( const double& val ) : + m_json( ::json_object_new_double( val ) ) +{ + if ( m_json == 0 ) + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_double" ) + << ValueErr( val ) + ) ; +} + +template <> +Json::Json( const boost::int32_t& l ) : m_json( ::json_object_new_int( l ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_int" ) + << ValueErr( l ) + ) ; } template <> -Json::Json( const long& l ) : - m_json( ::json_object_new_int( static_cast(l) ) ) +Json::Json( const boost::int64_t& l ) : + m_json( ::json_object_new_int64( l ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_int64" ) + << ValueErr( l ) + ) ; } template <> -Json::Json( const unsigned long& l ) : +Json::Json( const boost::uint32_t& l ) : m_json( ::json_object_new_int( static_cast(l) ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_int" ) + << ValueErr( l ) + ) ; +} + +template <> +Json::Json( const boost::uint64_t& l ) : + m_json( ::json_object_new_int64( l ) ) +{ + if ( m_json == 0 ) + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_int64" ) + << ValueErr( l ) + ) ; } template <> @@ -87,7 +146,7 @@ Json::Json( const std::vector& arr ) : m_json( ::json_object_new_array( ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json int" ) ) ; + BOOST_THROW_EXCEPTION( Error() << JsonCApi_( "json_object_new_array" ) ) ; for ( std::vector::const_iterator i = arr.begin() ; i != arr.end() ; ++i ) Add( *i ) ; @@ -98,7 +157,11 @@ Json::Json( const bool& b ) : m_json( ::json_object_new_boolean( b ) ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json bool" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_object_new_boolean" ) + << ValueErr( b ) + ) ; } template <> @@ -106,7 +169,7 @@ Json::Json( const Object& obj ) : m_json( ::json_object_new_object() ) { if ( m_json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "cannot create json object" ) ) ; + BOOST_THROW_EXCEPTION( Error() << JsonCApi_( "json_object_new_object" ) ) ; for ( Object::const_iterator i = obj.begin() ; i != obj.end() ; ++i ) Add( i->first, i->second ) ; @@ -157,13 +220,15 @@ Json Json::operator[]( const std::string& key ) const { assert( m_json != 0 ) ; - struct json_object *j = ::json_object_object_get( m_json, key.c_str() ) ; - if ( j == 0 ) + struct json_object *j = 0 ; + if ( !::json_object_object_get_ex( m_json, key.c_str(), &j ) ) BOOST_THROW_EXCEPTION( Error() - << expt::ErrMsg( "key: " + key + " is not found in object" ) - << JsonInfo( *this ) ) ; + << JsonCApi_( "json_object_object_get" ) + << KeyNotFound_( key ) + << Json_( ::json_object_to_json_string(m_json) ) ) ; + assert( j != 0 ) ; return Json( j ) ; } @@ -174,12 +239,11 @@ Json Json::operator[]( const std::size_t& idx ) const struct json_object *j = ::json_object_array_get_idx( m_json, idx ) ; if ( j == 0 ) { - std::ostringstream ss ; - ss << "index " << idx << " is not found in array" ; BOOST_THROW_EXCEPTION( Error() - << expt::ErrMsg( ss.str() ) - << JsonInfo( *this ) ) ; + << JsonCApi_( "json_object_array_get_idx" ) + << OutOfRange_( idx ) + << Json_( ::json_object_to_json_string(m_json) ) ) ; } return Json( j ) ; @@ -188,15 +252,17 @@ Json Json::operator[]( const std::size_t& idx ) const bool Json::Has( const std::string& key ) const { assert( m_json != 0 ) ; - return ::json_object_object_get( m_json, key.c_str() ) != 0 ; + return ::json_object_object_get_ex( m_json, key.c_str(), 0 ) == TRUE ; } bool Json::Get( const std::string& key, Json& json ) const { assert( m_json != 0 ) ; - struct json_object *j = ::json_object_object_get( m_json, key.c_str() ) ; - if ( j != 0 ) + struct json_object *j = 0 ; + if ( ::json_object_object_get_ex( m_json, key.c_str(), &j ) ) { + assert( j != 0 ) ; + Json tmp( j ) ; json.Swap( tmp ) ; return true ; @@ -226,14 +292,20 @@ void Json::Add( const Json& json ) bool Json::Bool() const { assert( m_json != 0 ) ; - return ::json_object_get_boolean( m_json ) ; + return ::json_object_get_boolean( m_json ) == TRUE ; } template <> bool Json::Is() const { assert( m_json != 0 ) ; - return ::json_object_is_type( m_json, json_type_boolean ) ; + return ::json_object_is_type( m_json, json_type_boolean ) == TRUE ; +} + +template <> +bool Json::As() const +{ + return Bool() ; } std::string Json::Str() const @@ -246,7 +318,13 @@ template <> bool Json::Is() const { assert( m_json != 0 ) ; - return ::json_object_is_type( m_json, json_type_string ) ; + return ::json_object_is_type( m_json, json_type_string ) == TRUE ; +} + +template <> +std::string Json::As() const +{ + return Str() ; } int Json::Int() const @@ -259,7 +337,31 @@ template <> bool Json::Is() const { assert( m_json != 0 ) ; - return ::json_object_is_type( m_json, json_type_int ) ; + return ::json_object_is_type( m_json, json_type_int ) == TRUE ; +} + +template <> +boost::int32_t Json::As() const +{ + return Int() ; +} + +template <> +boost::uint32_t Json::As() const +{ + return static_cast(Int()) ; +} + +template <> +boost::int64_t Json::As() const +{ + return ::json_object_get_int64( m_json ) ; +} + +template <> +boost::uint64_t Json::As() const +{ + return ::json_object_get_int64( m_json ) ; } std::ostream& operator<<( std::ostream& os, const Json& json ) @@ -268,10 +370,12 @@ std::ostream& operator<<( std::ostream& os, const Json& json ) return os << ::json_object_to_json_string( json.m_json ) ; } -void Json::Write( StdioFile& file ) const +void Json::Write( DataStream *out ) const { + assert( out != 0 ) ; + const char *str = ::json_object_to_json_string( m_json ) ; - file.Write( str, std::strlen(str) ) ; + out->Write( str, std::strlen(str) ) ; } Json::Type Json::DataType() const @@ -296,7 +400,13 @@ template <> bool Json::Is() const { assert( m_json != 0 ) ; - return ::json_object_is_type( m_json, json_type_object ) ; + return ::json_object_is_type( m_json, json_type_object ) == TRUE ; +} + +template <> +Json::Object Json::As() const +{ + return AsObject() ; } Json::Array Json::AsArray() const @@ -314,9 +424,18 @@ template <> bool Json::Is() const { assert( m_json != 0 ) ; - return ::json_object_is_type( m_json, json_type_array ) ; + return ::json_object_is_type( m_json, json_type_array ) == TRUE ; } +template <> +Json::Array Json::As() const +{ + return AsArray() ; +} + +/// Finds an element in the array. +/// \pre "this" is an array +/// \return *this[i] if *this[i][key] == value Json Json::FindInArray( const std::string& key, const std::string& value ) const { std::size_t count = ::json_object_array_length( m_json ) ; @@ -327,8 +446,16 @@ Json Json::FindInArray( const std::string& key, const std::string& value ) const if ( item.Has(key) && item[key].Str() == value ) return item ; } + BOOST_THROW_EXCEPTION( - Error() << expt::ErrMsg( "cannot find " + key + " = " + value + " in array" ) ) ; + Error() + << JsonCApi_( "Json::FindInArray" ) + << KeyNotFound_( key ) + << Value_(value) + ) ; + + // shut off compiler warnings + return Json() ; } bool Json::FindInArray( const std::string& key, const std::string& value, Json& result ) const @@ -340,37 +467,58 @@ bool Json::FindInArray( const std::string& key, const std::string& value, Json& } catch ( Error& ) { - return false ; } + return false ; } Json Json::Parse( const std::string& str ) { struct json_object *json = ::json_tokener_parse( str.c_str() ) ; if ( json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( "json parse error" ) ) ; + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_tokener_parse" ) + << ValueErr( str ) + ) ; return Json( json, NotOwned() ) ; } -Json Json::ParseFile( const std::string& filename ) +/// Parse a file. The file is loaded from file system. +/// \throw Error expt::ErrMsg contains a human-readable message describing the +/// error. +Json Json::Parse( DataStream *in ) { - StdioFile file( filename ) ; + assert( in != 0 ) ; + struct json_tokener *tok = ::json_tokener_new() ; - struct json_object *json = 0 ; char buf[1024] ; std::size_t count = 0 ; - while ( (count = file.Read( buf, sizeof(buf) ) ) > 0 ) + while ( (count = in->Read( buf, sizeof(buf) ) ) > 0 ) + { json = ::json_tokener_parse_ex( tok, buf, count ) ; + + // check for parse error + if ( ::json_tokener_get_error(tok) == ::json_tokener_continue ) + break ; + } - if ( json == 0 ) - BOOST_THROW_EXCEPTION( Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ) ; - - ::json_tokener_free( tok ) ; + // save the error code and free the tokener before throwing exceptions + ::json_tokener_error err = ::json_tokener_get_error(tok) ; + ::json_tokener_free( tok ) ; tok = 0 ; + if ( err != json_tokener_success || json == 0 ) + { + BOOST_THROW_EXCEPTION( + Error() + << JsonCApi_( "json_tokener_parse" ) + << expt::ErrMsg( ::json_tokener_error_desc(err) ) + ) ; + } + return Json( json, NotOwned() ) ; } diff --git a/libgrive/src/protocol/Json.hh b/libgrive/src/protocol/Json.hh index 034a4fc..a1f6bf0 100644 --- a/libgrive/src/protocol/Json.hh +++ b/libgrive/src/protocol/Json.hh @@ -29,8 +29,13 @@ struct json_object ; namespace gr { -class StdioFile ; +class DataStream ; +/*! \brief Simple wrapper around JSON-C objects. + + This class represents JSON-C objects, which can be integers, booleans, strings + double, arrays and object. +*/ class Json { public : @@ -38,19 +43,35 @@ public : typedef std::vector Array ; struct Error : virtual Exception {} ; - typedef boost::error_info JsonInfo ; - + typedef boost::error_info Json_ ; + typedef boost::error_info OutOfRange_ ; + typedef boost::error_info KeyNotFound_ ; + typedef boost::error_info JsonCApi_ ; + typedef boost::error_info Value_ ; + + template + struct Val_ + { + typedef boost::error_info Err ; + } ; + public : template explicit Json( const T& val ) ; + template + explicit Json( const char (&str)[n] ) : + m_json( InitStr( str, n ) ) + { + } + Json() ; Json( const Json& rhs ) ; Json( const char *str ) ; - ~Json( ) ; + ~Json() ; static Json Parse( const std::string& str ) ; - static Json ParseFile( const std::string& filename ) ; + static Json Parse( DataStream *in ) ; Json operator[]( const std::string& key ) const ; Json operator[]( const std::size_t& idx ) const ; @@ -68,6 +89,9 @@ public : template bool Is() const ; + template + T As() const ; + bool Has( const std::string& key ) const ; bool Get( const std::string& key, Json& json ) const ; void Add( const std::string& key, const Json& json ) ; @@ -76,7 +100,7 @@ public : bool FindInArray( const std::string& key, const std::string& value, Json& result ) const ; friend std::ostream& operator<<( std::ostream& os, const Json& json ) ; - void Write( StdioFile& file ) const ; + void Write( DataStream *out ) const ; enum Type { null_type, bool_type, double_type, int_type, object_type, array_type, string_type } ; @@ -87,10 +111,17 @@ private : struct NotOwned {} ; Json( struct json_object *json, NotOwned ) ; - + + static struct json_object* InitStr( const char *str, std::size_t n ) ; + + // helper for throwing exception + template static typename Val_::Err ValueErr( const T& t ) + { + return typename Val_::Err(t); + } + private : -public : struct json_object *m_json ; } ; -} \ No newline at end of file +} diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index 539e82c..6111b1d 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -19,7 +19,7 @@ #include "Config.hh" -#include "util/StdioFile.hh" +#include "util/File.hh" #include @@ -28,7 +28,7 @@ namespace po = boost::program_options; -namespace gr { +namespace PROJ_NS { const std::string default_filename = ".grive"; const char *env_name = "GR_CONFIG"; @@ -64,8 +64,8 @@ const fs::path Config::Filename() const void Config::Save( ) { - StdioFile file( m_path.string(), 0600 ) ; - m_file.Write( file ) ; + gr::File file( m_path.string(), 0600 ) ; + m_file.Write( &file ) ; } void Config::Set( const std::string& key, const Json& value ) @@ -93,7 +93,8 @@ Json Config::Read() { try { - return Json::ParseFile( m_path.string() ) ; + gr::File file(m_path) ; + return Json::Parse( &file ) ; } catch ( Exception& e ) { diff --git a/libgrive/src/util/Config.hh b/libgrive/src/util/Config.hh index e2c0423..6057f14 100644 --- a/libgrive/src/util/Config.hh +++ b/libgrive/src/util/Config.hh @@ -31,7 +31,7 @@ namespace boost } } -namespace gr { +namespace PROJ_NS { class Config { diff --git a/libgrive/src/util/Crypt.cc b/libgrive/src/util/Crypt.cc index 953767d..f0049f5 100644 --- a/libgrive/src/util/Crypt.cc +++ b/libgrive/src/util/Crypt.cc @@ -19,7 +19,7 @@ #include "Crypt.hh" -#include "StdioFile.hh" +#include "File.hh" #include "Exception.hh" #include "MemMap.hh" @@ -76,16 +76,16 @@ std::string MD5::Get( const fs::path& file ) { try { - StdioFile sfile( file ) ; + File sfile( file ) ; return Get( sfile ) ; } - catch ( StdioFile::Error& ) + catch ( File::Error& ) { return "" ; } } -std::string MD5::Get( StdioFile& file ) +std::string MD5::Get( File& file ) { MD5 crypt ; diff --git a/libgrive/src/util/Crypt.hh b/libgrive/src/util/Crypt.hh index 6126b53..6cd6ceb 100644 --- a/libgrive/src/util/Crypt.hh +++ b/libgrive/src/util/Crypt.hh @@ -26,7 +26,7 @@ namespace gr { -class StdioFile ; +class File ; namespace crypt { @@ -36,7 +36,7 @@ public : MD5() ; ~MD5() ; - static std::string Get( StdioFile& file ) ; + static std::string Get( File& file ) ; static std::string Get( const boost::filesystem::path& file ) ; void Write( const void *data, std::size_t size ) ; diff --git a/libgrive/src/util/DataStream.hh b/libgrive/src/util/DataStream.hh new file mode 100644 index 0000000..819c8f8 --- /dev/null +++ b/libgrive/src/util/DataStream.hh @@ -0,0 +1,55 @@ +/* + webwrite: an GPL program to sync a local directory with Google Drive + Copyright (C) 2012 Wan Wai Ho + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include + +namespace gr { + +/** \brief Encapsulation of data streams. Useful for unit tests. + This class provides two functions: Read() and Write(). +*/ +class DataStream +{ +protected : + virtual ~DataStream() {} + +public : + /** Reading from the stream. The caller indicates that it wants + to read `size` bytes and must provide enough space pointed + by `data`. + \param data Buffer to hold the data read from the stream + Must have at least `size` bytes. + \param size Number of bytes the caller wants to read. + \throw wb::Exception In case of any error. + \return The number of byte actually read from the stream. + 0 indicates the end of stream, i.e. you will + still get 0 if you call again. + */ + virtual std::size_t Read( char *data, std::size_t size ) = 0 ; + virtual std::size_t Write( const char *data, std::size_t size ) = 0 ; +} ; + +/// Stream for /dev/null, i.e. read and writing nothing +DataStream* DevNull() ; + + + +} // end of namespace diff --git a/libgrive/src/util/Exception.cc b/libgrive/src/util/Exception.cc index 68738b4..a410bbb 100644 --- a/libgrive/src/util/Exception.cc +++ b/libgrive/src/util/Exception.cc @@ -17,7 +17,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "util/Exception.hh" +#include "Exception.hh" #include "bfd/Backtrace.hh" #include "bfd/Debug.hh" @@ -28,15 +28,20 @@ #include #include -namespace gr { +namespace PROJ_NS { class Backtrace ; Exception::Exception( ) { #ifdef HAVE_BFD - *this << expt::BacktraceInfo( Backtrace() ) ; + *this << expt::Backtrace_( Backtrace() ) ; #endif } +const char* Exception::what() const throw() +{ + return boost::diagnostic_information_what( *this ) ; +} + } // end of namespace diff --git a/libgrive/src/util/Exception.hh b/libgrive/src/util/Exception.hh index fec5af7..164f9dd 100644 --- a/libgrive/src/util/Exception.hh +++ b/libgrive/src/util/Exception.hh @@ -1,5 +1,5 @@ /* - grive: an GPL program to sync a local directory with Google Drive + webwrite: an GPL program to sync a local directory with Google Drive Copyright (C) 2012 Wan Wai Ho This program is free software; you can redistribute it and/or @@ -25,54 +25,35 @@ #include #include -namespace gr { +namespace PROJ_NS { class Backtrace ; /** \defgroup exception Exception Classes */ -/// base class for exception in libpdfdoc -/** \ingroup exception - This class is the base class for all exception class in libpdfdoc. +/** \brief base class for exception in WebWrite + \ingroup exception + This class is the base class for all exception class in WebWrite. + It allows us to catch all WebWrite exception with one catch clause. */ struct Exception : virtual public std::exception, virtual public boost::exception { Exception( ) ; + + virtual const char* what() const throw() ; } ; -struct FileError : virtual Exception {} ; - -/// Parse error exception. -/** \ingroup exception - This exception will be thrown when there is a parse error when reading - a PDF file. -*/ -struct ParseError : virtual Exception {} ; - -/// Invalid type exception. -/** \ingroup exception - This exception will be thrown when the Object cannot convert its - underlying data to a specific type. The what() member function will - describe the expected and actual type of the data. -*/ -struct BadType : virtual Exception {} ; - -struct Unsupported : virtual Exception {} ; - -// Exception informations +/// Exception informations namespace expt { // back-trace information. should be present for all exceptions - typedef boost::error_info BacktraceInfo ; + typedef boost::error_info Backtrace_ ; - // generic error message - typedef boost::error_info ErrMsg ; - - // nested exception - typedef boost::error_info Nested ; + /// generic error message + typedef boost::error_info ErrMsg ; } } // end of namespace diff --git a/libgrive/src/util/StdioFile.cc b/libgrive/src/util/File.cc similarity index 63% rename from libgrive/src/util/StdioFile.cc rename to libgrive/src/util/File.cc index 435aea9..e6c047b 100644 --- a/libgrive/src/util/StdioFile.cc +++ b/libgrive/src/util/File.cc @@ -17,27 +17,34 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "StdioFile.hh" +#include "File.hh" #include // boost headers #include #include -#include #include #include #include #include -#include #include #include #include +#ifdef WIN32 + #include + typedef int ssize_t ; +#else + #include +#endif + // local functions namespace { +using namespace gr ; + off_t LSeek( int fd, off_t offset, int whence ) { assert( fd >= 0 ) ; @@ -46,7 +53,7 @@ off_t LSeek( int fd, off_t offset, int whence ) if ( r == static_cast(-1) ) { BOOST_THROW_EXCEPTION( - gr::StdioFile::Error() + File::Error() << boost::errinfo_api_function("lseek") << boost::errinfo_errno(errno) ) ; @@ -61,7 +68,7 @@ struct stat FStat( int fd ) if ( ::fstat( fd, &s ) != 0 ) { BOOST_THROW_EXCEPTION( - gr::StdioFile::Error() + File::Error() << boost::errinfo_api_function("fstat") << boost::errinfo_errno(errno) ) ; @@ -71,28 +78,40 @@ struct stat FStat( int fd ) } // end of local functions -namespace gr { +namespace PROJ_NS { -StdioFile::StdioFile( ) : m_fd( -1 ) +File::File( ) : m_fd( -1 ) { } -StdioFile::StdioFile( const fs::path& path ) : m_fd( -1 ) +/** Opens the file for reading. + \param path Path to the file to be opened. + \throw Error When the file cannot be openned. +*/ +File::File( const fs::path& path ) : m_fd( -1 ) { OpenForRead( path ) ; } -StdioFile::StdioFile( const fs::path& path, int mode ) : m_fd( -1 ) +/** Opens the file for writing. + \param path Path to the file to be opened. + \param mode Mode of the file to be created, e.g. 0600 for user + readable/writable. + \throw Error When the file cannot be opened. +*/ +File::File( const fs::path& path, int mode ) : m_fd( -1 ) { OpenForWrite( path, mode ) ; } -StdioFile::~StdioFile( ) +/** The destructor will close the file. +*/ +File::~File( ) { Close() ; } -void StdioFile::Open( const fs::path& path, int flags, int mode ) +void File::Open( const fs::path& path, int flags, int mode ) { if ( IsOpened() ) Close() ; @@ -110,17 +129,25 @@ void StdioFile::Open( const fs::path& path, int flags, int mode ) } } -void StdioFile::OpenForRead( const fs::path& path ) +void File::OpenForRead( const fs::path& path ) { - Open( path, O_RDONLY, 0 ) ; + int flags = O_RDONLY ; +#ifdef WIN32 + flags |= O_BINARY ; +#endif + Open( path, flags, 0 ) ; } -void StdioFile::OpenForWrite( const fs::path& path, int mode ) +void File::OpenForWrite( const fs::path& path, int mode ) { - Open( path, O_CREAT|O_RDWR|O_TRUNC, mode ) ; + int flags = O_CREAT|O_RDWR|O_TRUNC ; +#ifdef WIN32 + flags |= O_BINARY ; +#endif + Open( path, flags, mode ) ; } -void StdioFile::Close() +void File::Close() { if ( IsOpened() ) { @@ -129,12 +156,15 @@ void StdioFile::Close() } } -bool StdioFile::IsOpened() const +bool File::IsOpened() const { return m_fd != -1 ; } -std::size_t StdioFile::Read( void *ptr, std::size_t size ) +/** Read bytes from file. See DataStream::Read() for details. + \throw Error In case of any error. +*/ +std::size_t File::Read( char *ptr, std::size_t size ) { assert( IsOpened() ) ; ssize_t count = ::read( m_fd, ptr, size ) ; @@ -149,7 +179,7 @@ std::size_t StdioFile::Read( void *ptr, std::size_t size ) return count ; } -std::size_t StdioFile::Write( const void *ptr, std::size_t size ) +std::size_t File::Write( const char *ptr, std::size_t size ) { assert( IsOpened() ) ; ssize_t count = ::write( m_fd, ptr, size ) ; @@ -157,26 +187,26 @@ std::size_t StdioFile::Write( const void *ptr, std::size_t size ) { BOOST_THROW_EXCEPTION( Error() - << boost::errinfo_api_function("read") + << boost::errinfo_api_function("write") << boost::errinfo_errno(errno) ) ; } return count ; } -off_t StdioFile::Seek( off_t offset, int whence ) +off_t File::Seek( off_t offset, int whence ) { assert( IsOpened() ) ; return LSeek( m_fd, offset, whence ) ; } -off_t StdioFile::Tell() const +off_t File::Tell() const { assert( IsOpened() ) ; return LSeek( m_fd, 0, SEEK_CUR ) ; } -u64_t StdioFile::Size() const +u64_t File::Size() const { assert( IsOpened() ) ; @@ -186,10 +216,10 @@ u64_t StdioFile::Size() const return static_cast( s.st_size ) ; } -void StdioFile::Chmod( int mode ) +void File::Chmod( int mode ) { assert( IsOpened() ) ; - +#ifndef WIN32 if ( ::fchmod( m_fd, mode ) != 0 ) { BOOST_THROW_EXCEPTION( @@ -198,12 +228,18 @@ void StdioFile::Chmod( int mode ) << boost::errinfo_errno(errno) ) ; } +#endif } -void* StdioFile::Map( off_t offset, std::size_t length ) +/// This function is not implemented in win32 yet. +void* File::Map( off_t offset, std::size_t length ) { assert( IsOpened() ) ; +#ifdef WIN32 + assert( false ) ; + return 0 ; +#else void *addr = ::mmap( 0, length, PROT_READ, MAP_PRIVATE, m_fd, offset ) ; if ( addr == reinterpret_cast( -1 ) ) { @@ -214,10 +250,12 @@ void* StdioFile::Map( off_t offset, std::size_t length ) ) ; } return addr ; +#endif } -void StdioFile::UnMap( void *addr, std::size_t length ) +void File::UnMap( void *addr, std::size_t length ) { +#ifndef WIN32 if ( ::munmap( addr, length ) != 0 ) { BOOST_THROW_EXCEPTION( @@ -226,6 +264,21 @@ void StdioFile::UnMap( void *addr, std::size_t length ) << boost::errinfo_errno(errno) ) ; } +#endif +} + +struct stat File::Stat() const +{ + struct stat result = {} ; + if ( ::fstat( m_fd, &result ) != 0 ) + { + BOOST_THROW_EXCEPTION( + Error() + << boost::errinfo_api_function("fstat") + << boost::errinfo_errno(errno) + ) ; + } + return result ; } } // end of namespace diff --git a/libgrive/src/util/StdioFile.hh b/libgrive/src/util/File.hh similarity index 66% rename from libgrive/src/util/StdioFile.hh rename to libgrive/src/util/File.hh index 21443b6..041c599 100644 --- a/libgrive/src/util/StdioFile.hh +++ b/libgrive/src/util/File.hh @@ -19,32 +19,47 @@ #pragma once +#include "DataStream.hh" #include "Exception.hh" #include "FileSystem.hh" #include "Types.hh" #include +struct stat ; + namespace gr { -class StdioFile +/** \brief A wrapper class for file read/write. + + It is a simple wrapper around the UNIX file descriptor. It will + throw exceptions (i.e. Error) when it encounters errors. +*/ +class File : public DataStream { public : + /// File specific errors. It often includes + /// boost::errinfo_api_function and boost::errinfo_errno for the + /// detail information. struct Error : virtual Exception {} ; public : - StdioFile() ; - StdioFile( const fs::path& path ) ; - StdioFile( const fs::path& path, int mode ) ; - ~StdioFile( ) ; + File() ; + File( const fs::path& path ) ; + File( const fs::path& path, int mode ) ; + ~File( ) ; + + File( const File& rhs ) ; + File& operator=( const File& rhs ) ; + void Swap( File& other ) ; void OpenForRead( const fs::path& path ) ; void OpenForWrite( const fs::path& path, int mode = 0600 ) ; void Close() ; bool IsOpened() const ; - std::size_t Read( void *ptr, std::size_t size ) ; - std::size_t Write( const void *ptr, std::size_t size ) ; + std::size_t Read( char *ptr, std::size_t size ) ; + std::size_t Write( const char *ptr, std::size_t size ) ; off_t Seek( off_t offset, int whence ) ; off_t Tell() const ; @@ -54,7 +69,9 @@ public : void* Map( off_t offset, std::size_t length ) ; static void UnMap( void *addr, std::size_t length ) ; - + + struct stat Stat() const ; + private : void Open( const fs::path& path, int flags, int mode ) ; diff --git a/libgrive/src/util/FileSystem.hh b/libgrive/src/util/FileSystem.hh index f6c18ac..9eb02d3 100644 --- a/libgrive/src/util/FileSystem.hh +++ b/libgrive/src/util/FileSystem.hh @@ -25,17 +25,4 @@ namespace gr { namespace fs = boost::filesystem ; - - // these two functions are for ancient distro which does not have boost v1.44 or later - // will be removed once people upgrade - - inline std::string Path2Str( const fs::path& p ) - { - return p.string() ; - } - - inline std::string Path2Str( const std::string& s ) - { - return s ; - } } diff --git a/libgrive/src/util/MemMap.cc b/libgrive/src/util/MemMap.cc index 6f8b4c7..12b1f78 100644 --- a/libgrive/src/util/MemMap.cc +++ b/libgrive/src/util/MemMap.cc @@ -18,11 +18,11 @@ */ #include "MemMap.hh" -#include "StdioFile.hh" +#include "File.hh" namespace gr { -MemMap::MemMap( StdioFile& file, off_t offset, std::size_t length ) : +MemMap::MemMap( File& file, off_t offset, std::size_t length ) : m_addr ( file.Map( offset, length ) ), m_length( length ) { @@ -30,7 +30,7 @@ MemMap::MemMap( StdioFile& file, off_t offset, std::size_t length ) : MemMap::~MemMap() { - StdioFile::UnMap( m_addr, m_length ) ; + File::UnMap( m_addr, m_length ) ; } void* MemMap::Addr() const diff --git a/libgrive/src/util/MemMap.hh b/libgrive/src/util/MemMap.hh index 91a3033..b8ca5a2 100644 --- a/libgrive/src/util/MemMap.hh +++ b/libgrive/src/util/MemMap.hh @@ -25,7 +25,7 @@ namespace gr { -class StdioFile ; +class File ; class MemMap { @@ -33,7 +33,7 @@ public : struct Error : virtual Exception {} ; public : - MemMap( StdioFile& file, off_t offset, std::size_t length ) ; + MemMap( File& file, off_t offset, std::size_t length ) ; ~MemMap() ; void* Addr() const ;