[vlc-devel] [PATCH 3/8] gui/skins2: add ThemeLoader::unarchive

Rémi Denis-Courmont remi at remlab.net
Fri Jan 13 05:47:03 CET 2017


On January 13, 2017 2:21:18 AM GMT+08:00, "Filip Roséen" <filip at atch.se> wrote:
>---
>
>This implementation could be written in a cleaner manner, but it
>requires changes to the core. I will submit an independent patch for a
>refactor of this function at a later time (when some upcoming (soon to
>be proposed) minor changes to the core have been discussed).
>
>---
>modules/gui/skins2/src/theme_loader.cpp | 107
>++++++++++++++++++++++++++++++++
> modules/gui/skins2/src/theme_loader.hpp |   2 +
> 2 files changed, 109 insertions(+)
>
>diff --git a/modules/gui/skins2/src/theme_loader.cpp
>b/modules/gui/skins2/src/theme_loader.cpp
>index 31f1c550df..fb0811d4b4 100644
>--- a/modules/gui/skins2/src/theme_loader.cpp
>+++ b/modules/gui/skins2/src/theme_loader.cpp
>@@ -29,9 +29,13 @@
> #include <fcntl.h>
> #include <sys/stat.h>
> #include <unistd.h>
>+#include <fstream>
>+#include <memory>
> 
> #include <vlc_common.h>
> #include <vlc_fs.h>
>+#include <vlc_url.h>
>+#include <vlc_stream_extractor.h>
> 
> #include "theme_loader.hpp"
> #include "theme.hpp"
>@@ -351,6 +355,109 @@ bool ThemeLoader::extract( const std::string
>&fileName )
>     return result;
> }
> 
>+bool ThemeLoader::unarchive( const std::string& fileName, const
>std::string &tempPath )
>+{
>+#define UPTR_HELPER(type,deleter) []( type * data ) { \
>+        return std::unique_ptr< type, decltype( deleter )> ( data,
>deleter ); }
>+
>+    auto make_input_node_ptr = UPTR_HELPER( input_item_node_t,
>&input_item_node_Delete );
>+    auto make_input_item_ptr = UPTR_HELPER( input_item_t,
>&input_item_Release );
>+    auto make_stream_ptr = UPTR_HELPER( stream_t, &vlc_stream_Delete
>);
>+    auto make_cstr_ptr = UPTR_HELPER( char, &std::free );
>+
>+#undef UPTR_HELPER
>+
>+    auto uri = make_cstr_ptr( vlc_path2uri( fileName.c_str(), "file" )
>);
>+    if( !uri )
>+    {
>+        msg_Err( getIntf(), "unable to convert %s to local URI",
>+                            fileName.c_str() );
>+        return false;
>+    }
>+
>+    auto input = make_stream_ptr( vlc_stream_NewURL( getIntf(),
>uri.get() ) );
>+    if( !input )
>+    {
>+        msg_Err( getIntf(), "unable to open %s", uri.get() );
>+        return false;
>+    }
>+
>+    stream_t* stream = input.get();
>+    if( vlc_stream_extractor_Attach( &stream, NULL, NULL ) )
>+    {
>+        msg_Err( getIntf(), "unable to attach extractor, treat as
>XML!" );
>+    }
>+    else
>+    {
>+        input.release();
>+        input.reset( stream );
>+
>+        auto item = make_input_item_ptr( input_item_New(
>"vlc://dummy", "vlc://dummy" ) );
>+        auto node = make_input_node_ptr(
>(input_item_node_t*)std::calloc( 1, sizeof( input_item_node_t ) ) );
>+
>+        if( !item || !node )
>+            return false;
>+
>+        node->p_item = item.release();
>+
>+        if( vlc_stream_ReadDir( input.get(), node.get() ) )
>+        {
>+            msg_Err( getIntf(), "unable to read items in %s",
>uri.get() );
>+            return false;
>+        }
>+
>+        for( int i = 0; i < node->i_children; ++i )
>+        {
>+            auto child = node->pp_children[i]->p_item;
>+            auto child_stream = make_stream_ptr( vlc_stream_NewURL(
>getIntf(), uri.get() ) );
>+            if( !child_stream )
>+            {
>+                msg_Err( getIntf(), "unable to open %s for reading",
>child->psz_name );
>+            }
>+
>+            stream_t* stream = child_stream.get();
>+            if( vlc_stream_extractor_Attach( &stream, child->psz_name,
>NULL ) )
>+            {
>+                msg_Err( getIntf(), "unable to locate %s within %s",
>+                         child->psz_name, fileName.c_str() );
>+
>+                return false;
>+            }
>+
>+            child_stream.release();
>+            child_stream.reset( stream );
>+
>+            auto out_path = tempPath + "/" + child->psz_name;
>+
>+            { /* create directory tree */
>+                auto out_directory = out_path.substr( 0,
>out_path.find_last_of( '/' ) );
>+
>+                if( makedir( out_directory.c_str() ) == false )
>+                {
>+                    msg_Err( getIntf(), "failed to create directory
>tree for %s (%s)",
>+                             out_path.c_str(), out_directory.c_str()
>);
>+
>+                    return false;
>+                }
>+            }
>+
>+            { /* write data to disk */
>+                std::ofstream out_stream( out_path, std::ios::binary
>);
>+
>+                char buf[1024];
>+                ssize_t n;
>+
>+                while( ( n = vlc_stream_Read( child_stream.get(), buf,
>sizeof buf ) ) > 0 )
>+                    out_stream.write( buf, n );
>+
>+                msg_Dbg( getIntf(), "finished writing %zu bytes to
>%s",
>+                    size_t{ out_stream.tellp() }, out_path.c_str() );
>+            }
>+        }
>+    }
>+
>+    return true;
>+}
> 
> void ThemeLoader::deleteTempFiles( const std::string &path )
> {
>diff --git a/modules/gui/skins2/src/theme_loader.hpp
>b/modules/gui/skins2/src/theme_loader.hpp
>index b922cd367f..e5b35b150f 100644
>--- a/modules/gui/skins2/src/theme_loader.hpp
>+++ b/modules/gui/skins2/src/theme_loader.hpp
>@@ -48,6 +48,8 @@ private:
>      */
>     bool extract( const std::string &fileName );
> 
>+    bool unarchive( const std::string &fileName, const std::string
>&tempPath );
>+
>     /// Extract files from a tar.gz archive
>     /**
>      * Expects strings from the current locale.
>-- 
>2.11.0
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

Does C++ file I/O handle the atomic close on exec flag correctly? Does it handle character sets correctly (especially on Windows)? And even if it does, do we want yet another file I/O API?
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list