From b25dab9e6c7abba9a115adde7ca3259fb89a3124 Mon Sep 17 00:00:00 2001 From: Gerhard Raven <gerhard.raven@nikhef.nl> Date: Tue, 15 Mar 2022 09:33:29 +0100 Subject: [PATCH] Extend IFileAccess interface with a `read` function `IFileAccess;:read` returns an `optional<string>` with the content of the requested file -- if it can be read. Otherwise it returns an 'empty' optional. --- GaudiKernel/include/GaudiKernel/IFileAccess.h | 14 +++- .../include/GaudiKernel/ServiceHandle.h | 4 +- GaudiUtils/src/component/FileReadTool.cpp | 44 +++++++---- GaudiUtils/src/component/FileReadTool.h | 36 --------- GaudiUtils/src/component/VFSSvc.cpp | 74 ++++++++++++++----- GaudiUtils/src/component/VFSSvc.h | 70 ------------------ 6 files changed, 97 insertions(+), 145 deletions(-) delete mode 100644 GaudiUtils/src/component/FileReadTool.h delete mode 100644 GaudiUtils/src/component/VFSSvc.h diff --git a/GaudiKernel/include/GaudiKernel/IFileAccess.h b/GaudiKernel/include/GaudiKernel/IFileAccess.h index ae195089c7..07e438c884 100644 --- a/GaudiKernel/include/GaudiKernel/IFileAccess.h +++ b/GaudiKernel/include/GaudiKernel/IFileAccess.h @@ -15,6 +15,7 @@ #include "GaudiKernel/IInterface.h" #include <istream> #include <memory> +#include <optional> #include <string> #include <vector> @@ -28,12 +29,21 @@ class GAUDI_API IFileAccess : virtual public IInterface { public: /// InterfaceID - DeclareInterfaceID( IFileAccess, 3, 0 ); + DeclareInterfaceID( IFileAccess, 3, 1 ); /// Find the URL and returns a unique_ptr to an input stream interface of an /// object that can be used to read from the file the URL is pointing to. /// Returns an empty pointer if the URL cannot be resolved. - virtual std::unique_ptr<std::istream> open( const std::string& url ) = 0; + virtual std::unique_ptr<std::istream> open( std::string const& url ) = 0; + + /// Find the URL and returns an optional<string> to the content of + /// the file the URL is pointing to. + /// Returns an 'unengaged' optional if the URL cannot be resolved. + virtual std::optional<std::string> read( std::string const& url ) { + auto is = open( url ); + if ( !is || !is->good() ) return std::nullopt; + return std::string{ std::istreambuf_iterator<char>{ *is }, std::istreambuf_iterator<char>{} }; + } /// Protocols supported by the instance. virtual const std::vector<std::string>& protocols() const = 0; diff --git a/GaudiKernel/include/GaudiKernel/ServiceHandle.h b/GaudiKernel/include/GaudiKernel/ServiceHandle.h index 06d395be5e..93af3f82b6 100644 --- a/GaudiKernel/include/GaudiKernel/ServiceHandle.h +++ b/GaudiKernel/include/GaudiKernel/ServiceHandle.h @@ -77,9 +77,7 @@ public: /** Retrieve the Service. Release existing Service if needed. Function must be repeated here to avoid hiding the function retrieve( T*& ) */ - StatusCode retrieve() const { // not really const, because it updates m_pObject - return GaudiHandle<T>::retrieve(); - } + using GaudiHandle<T>::retrieve; // /** Release the Service. // Function must be repeated here to avoid hiding the function release( T*& ) */ diff --git a/GaudiUtils/src/component/FileReadTool.cpp b/GaudiUtils/src/component/FileReadTool.cpp index b01f9add6b..573d6d1286 100644 --- a/GaudiUtils/src/component/FileReadTool.cpp +++ b/GaudiUtils/src/component/FileReadTool.cpp @@ -8,24 +8,36 @@ * granted to it by virtue of its status as an Intergovernmental Organization * * or submit itself to any jurisdiction. * \***********************************************************************************/ -#include "FileReadTool.h" +#include "GaudiKernel/AlgTool.h" +#include "GaudiKernel/IFileAccess.h" #include <fstream> -DECLARE_COMPONENT( FileReadTool ) +/** @class FileReadTool FileReadTool.h + * + * Basic implementation of the IFileAccess interface. + * This tool simply takes a path to a file as url and return the std::istream interface + * of std::ifstream. + * + * @author Marco Clemencic + * @date 2008-01-18 + */ +struct FileReadTool : extends<AlgTool, IFileAccess> { + /// Standard constructor + using extends::extends; + + std::unique_ptr<std::istream> open( std::string const& url ) override { + // remove the optional "file://" from the beginning of the url + constexpr auto prefix = std::string_view{ "file://" }; + return std::make_unique<std::ifstream>( url.compare( 0, prefix.size(), prefix ) == 0 ? url.substr( prefix.size() ) + : url ); + } -std::unique_ptr<std::istream> FileReadTool::open( const std::string& url ) { - // remove the optional "file://" from the beginning of the url - std::string path; - if ( url.compare( 0, 7, "file://" ) == 0 ) { - path = url.substr( 7 ); - } else { - path = url; + /// Protocols supported by the instance. + const std::vector<std::string>& protocols() const override { + /// Vector of supported protocols. + static const std::vector<std::string> s_protocols = { { "file" } }; + return s_protocols; } - return std::make_unique<std::ifstream>( path ); -} +}; -const std::vector<std::string>& FileReadTool::protocols() const { - /// Vector of supported protocols. - static const std::vector<std::string> s_protocols = { { "file" } }; - return s_protocols; -} +DECLARE_COMPONENT( FileReadTool ) diff --git a/GaudiUtils/src/component/FileReadTool.h b/GaudiUtils/src/component/FileReadTool.h deleted file mode 100644 index bcc061e81b..0000000000 --- a/GaudiUtils/src/component/FileReadTool.h +++ /dev/null @@ -1,36 +0,0 @@ -/***********************************************************************************\ -* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations * -* * -* This software is distributed under the terms of the Apache version 2 licence, * -* copied verbatim in the file "LICENSE". * -* * -* In applying this licence, CERN does not waive the privileges and immunities * -* granted to it by virtue of its status as an Intergovernmental Organization * -* or submit itself to any jurisdiction. * -\***********************************************************************************/ -#ifndef _FILEREADTOOL_H -#define _FILEREADTOOL_H - -#include "GaudiKernel/AlgTool.h" -#include "GaudiKernel/IFileAccess.h" - -/** @class FileReadTool FileReadTool.h - * - * Basic implementation of the IFileAccess interface. - * This tool simply takes a path to a file as url and return the std::istream interface - * of std::ifstream. - * - * @author Marco Clemencic - * @date 2008-01-18 - */ -struct FileReadTool : extends<AlgTool, IFileAccess> { - /// Standard constructor - using extends::extends; - - std::unique_ptr<std::istream> open( const std::string& url ) override; - - /// Protocols supported by the instance. - const std::vector<std::string>& protocols() const override; -}; - -#endif // _FILEREADTOOL_H diff --git a/GaudiUtils/src/component/VFSSvc.cpp b/GaudiUtils/src/component/VFSSvc.cpp index a40b718ec1..85b29db6e7 100644 --- a/GaudiUtils/src/component/VFSSvc.cpp +++ b/GaudiUtils/src/component/VFSSvc.cpp @@ -8,11 +8,58 @@ * granted to it by virtue of its status as an Intergovernmental Organization * * or submit itself to any jurisdiction. * \***********************************************************************************/ -#include "VFSSvc.h" - +#include "GaudiKernel/HashMap.h" #include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/IFileAccess.h" #include "GaudiKernel/IToolSvc.h" #include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Service.h" +#include <list> + +/** @class VFSSvc VFSSvc.h + * + * Simple service that allows to read files independently from the storage. + * The service uses tools to resolve URLs and serve the files as input streams. + * The basic implementations read from the filesystem, and simple extensions allow to + * read from databases, web... + * + * @author Marco Clemencic + * @date 2008-01-18 + */ + +class VFSSvc : public extends<Service, IFileAccess> { +public: + /// Inherited constructor + using extends::extends; + /// Initialize Service + StatusCode initialize() override; + /// Finalize Service + StatusCode finalize() override; + + /// @see IFileAccess::open + std::unique_ptr<std::istream> open( std::string const& url ) override; + + /// @see IFileAccess::protocols + const std::vector<std::string>& protocols() const override; + +private: + Gaudi::Property<std::vector<std::string>> m_urlHandlersNames{ + this, "FileAccessTools", { { "FileReadTool" } }, "List of tools implementing the IFileAccess interface." }; + Gaudi::Property<std::string> m_fallBackProtocol{ this, "FallBackProtocol", "file", + "URL prefix to use if the prefix is not present." }; + + /// Protocols registered + std::vector<std::string> m_protocols; + + /// Map of the tools handling the known protocols. + GaudiUtils::HashMap<std::string, std::vector<IFileAccess*>> m_urlHandlers; + + /// Handle to the tool service. + SmartIF<IToolSvc> m_toolSvc; + + /// List of acquired tools (needed to release them). + std::vector<IAlgTool*> m_acquiredTools; +}; DECLARE_COMPONENT( VFSSvc ) @@ -73,13 +120,13 @@ StatusCode VFSSvc::finalize() { return Service::finalize(); } //------------------------------------------------------------------------------ -std::unique_ptr<std::istream> VFSSvc::open( const std::string& url ) { +std::unique_ptr<std::istream> VFSSvc::open( std::string const& url ) { // get the url prefix endpos auto pos = url.find( "://" ); - if ( std::string::npos == pos ) { + if ( url.npos == pos ) { // no url prefix, try fallback protocol - return VFSSvc::open( m_fallBackProtocol + "://" + url ); + return VFSSvc::open( std::string{ m_fallBackProtocol }.append( "://" ).append( url ) ); } const std::string url_prefix( url, 0, pos ); @@ -87,7 +134,7 @@ std::unique_ptr<std::istream> VFSSvc::open( const std::string& url ) { if ( handlers == m_urlHandlers.end() ) { // if we do not have a handler for the URL prefix, // use the fall back one - return VFSSvc::open( m_fallBackProtocol + url.substr( pos ) ); + return VFSSvc::open( std::string{ m_fallBackProtocol }.append( url.substr( pos ) ) ); } std::unique_ptr<std::istream> out; // this might help RVO @@ -98,23 +145,14 @@ std::unique_ptr<std::istream> VFSSvc::open( const std::string& url ) { } return out; } -//------------------------------------------------------------------------------ -namespace { - /// small helper to select the first element of a pair - /// (e.g. the key of a map value type) - constexpr struct select1st_t { - template <typename S, typename T> - const S& operator()( const std::pair<S, T>& x ) const { - return x.first; - } - } select1st{}; -} // namespace +//------------------------------------------------------------------------------ const std::vector<std::string>& VFSSvc::protocols() const { if ( m_protocols.empty() ) { // prepare the list of handled protocols std::transform( m_urlHandlers.begin(), m_urlHandlers.end(), - std::back_inserter( const_cast<VFSSvc*>( this )->m_protocols ), select1st ); + std::back_inserter( const_cast<VFSSvc*>( this )->m_protocols ), + []( const auto& pair ) { return pair.first; } ); } return m_protocols; } diff --git a/GaudiUtils/src/component/VFSSvc.h b/GaudiUtils/src/component/VFSSvc.h deleted file mode 100644 index c4417f4b67..0000000000 --- a/GaudiUtils/src/component/VFSSvc.h +++ /dev/null @@ -1,70 +0,0 @@ -/***********************************************************************************\ -* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations * -* * -* This software is distributed under the terms of the Apache version 2 licence, * -* copied verbatim in the file "LICENSE". * -* * -* In applying this licence, CERN does not waive the privileges and immunities * -* granted to it by virtue of its status as an Intergovernmental Organization * -* or submit itself to any jurisdiction. * -\***********************************************************************************/ -#ifndef GaudiSvc_VFSSvc_H -#define GaudiSvc_VFSSvc_H 1 - -// Include files -#include "GaudiKernel/HashMap.h" -#include "GaudiKernel/IFileAccess.h" -#include "GaudiKernel/Service.h" - -#include <list> - -// Forward declarations -class IToolSvc; -class IAlgTool; - -/** @class VFSSvc VFSSvc.h - * - * Simple service that allows to read files independently from the storage. - * The service uses tools to resolve URLs and serve the files as input streams. - * The basic implementations read from the filesystem, and simple extensions allow to - * read from databases, web... - * - * @author Marco Clemencic - * @date 2008-01-18 - */ - -class VFSSvc : public extends<Service, IFileAccess> { -public: - /// Inherited constructor - using extends::extends; - /// Initialize Service - StatusCode initialize() override; - /// Finalize Service - StatusCode finalize() override; - - /// @see IFileAccess::open - std::unique_ptr<std::istream> open( const std::string& url ) override; - - /// @see IFileAccess::protocols - const std::vector<std::string>& protocols() const override; - -private: - Gaudi::Property<std::vector<std::string>> m_urlHandlersNames{ - this, "FileAccessTools", { { "FileReadTool" } }, "List of tools implementing the IFileAccess interface." }; - Gaudi::Property<std::string> m_fallBackProtocol{ this, "FallBackProtocol", "file", - "URL prefix to use if the prefix is not present." }; - - /// Protocols registered - std::vector<std::string> m_protocols; - - /// Map of the tools handling the known protocols. - GaudiUtils::HashMap<std::string, std::vector<IFileAccess*>> m_urlHandlers; - - /// Handle to the tool service. - SmartIF<IToolSvc> m_toolSvc; - - /// List of acquired tools (needed to release them). - std::vector<IAlgTool*> m_acquiredTools; -}; - -#endif -- GitLab