[ create a new paste ] login | about

Link: http://codepad.org/oVH0lkbm    [ raw code | fork ]

C++, pasted on Oct 24:
#pragma once

//--------------------------------------------------- Dependencies:

#include "throwx.h"                 // throwX, hopefully
#include "NullPointer.h"            // nullPointer
#include "is_explicitly_convertible.h"      // IsExplicitlyConvertibleTo template.
#include "wrapper/windows_h.h"

#include <array>                    // std::array
#include <algorithm>                // std::swap
#include <fstream>                  // std::ifstream, std::ofstream
#include <stdlib.h>                 // wcstombs
#include <string>                   // std::string, std::wstring
#include <type_traits>              // std::conditional

#include <iostream>


//--------------------------------------------------- Interface:

namespace windows {
    using std::array;
    using std::ifstream;
    using std::exception;
    using std::ofstream;
    using std::string;
    using std::wstring;

    inline wstring shortPathFor( wstring const& filename )
    {
        array< wchar_t, MAX_PATH >  buffer;
        
        DWORD const nChars      =
            GetShortPathName( filename.c_str(), buffer.data(), buffer.size() );
        hopefully( 0 < nChars && nChars < buffer.size() )
            || throwX( "windows::shortPathFor failed because GetShortPathName failed" );
        return buffer.data();
    }

    inline bool getPerfectAnsiFor( wstring const& ws, string& perfectAnsi )
    {
        using std::swap;
        std::string     result( ws.length() + 1, '@' );
        
        size_t const nChars  = wcstombs( &result[0], ws.c_str(), result.size() );
        if( nChars == size_t( -1 ) )
        {
            return false;
        }
        result.resize( nChars );
        swap( result, perfectAnsi );
        return true;
    }

    inline string ansiInfileName(
        wstring const&      filename,
        bool                tryPerfectConversionFirst = true
        )
    {
        string      result;

        if( tryPerfectConversionFirst )
        {
            if( getPerfectAnsiFor( filename, result ) )
            {
                return result;
            }
        }
        if( getPerfectAnsiFor( shortPathFor( filename ), result ) )
        {
            return result;
        }
        throwX( "windows::ansiInfileName failed" );
    }

    inline string ansiOutfileName( wstring const& filename )
    {
        try
        {
            return ansiInfileName( filename );
        }
        catch( exception const& )
        {
            HANDLE const    f   = CreateFile(
                filename.c_str(), 0, 0, nullPointer, CREATE_NEW, 0, 0
                );
            hopefully( f != INVALID_HANDLE_VALUE )
                || "ansiOutfileName failed because CreateFile failed";
            CloseHandle( f );
            return ansiInfileName( filename, false );   // Have tried perfect conversion.
        }
    }

    namespace detail {
        class InFStreamAdapter
            : public ifstream
        {
        public:
            InFStreamAdapter() {}
            
            explicit
            InFStreamAdapter( char const* filename, ios_base::openmode  mode )
                : ifstream( filename, mode )
            {}
            
            explicit
            InFStreamAdapter( wchar_t const* filename, ios_base::openmode  mode )
                : ifstream( ansiInfileName( filename ).c_str(), mode )
            {}
        };
        
        class OutFStreamAdapter
            : public ofstream
        {
        public:
            OutFStreamAdapter() {}
            
            explicit
            OutFStreamAdapter( char const* filename, ios_base::openmode  mode )
                : ofstream( filename, mode )
            {}
            
            explicit
            OutFStreamAdapter( wchar_t const* filename, ios_base::openmode  mode )
                : ofstream( ansiOutfileName( filename ).c_str(), mode )
            {}
        };

        bool const  streamsSupportWideNames     =
            IsExplicitlyConvertibleTo< ofstream, wchar_t const* >::yes;
            
        typedef std::conditional<
            streamsSupportWideNames, ifstream, InFStreamAdapter
            >::type
            InFStreamBase;
        typedef std::conditional<
            streamsSupportWideNames, ofstream, OutFStreamAdapter
            >::type
            OutFStreamBase;
    }  // namespace detail

    class InFStream
        : public detail::InFStreamBase
    {
    private:
        typedef detail::InFStreamBase       Base;

    public:
        InFStream() {}

        explicit
        InFStream( char const* filename, ios_base::openmode mode = ios_base::in )
            : Base( filename, mode )
        {}

        explicit
        InFStream( string const& filename, ios_base::openmode mode = ios_base::in )
            : Base( filename.c_str(), mode )
        {}

        explicit
        InFStream( wchar_t const* filename, ios_base::openmode mode = ios_base::in )
            : Base( filename, mode )
        {}

        explicit
        InFStream( wstring const& filename, ios_base::openmode mode = ios_base::in )
            : Base( filename.c_str(), mode )
        {}
    };

    class OutFStream
        : public detail::OutFStreamBase
    {
    private:
        typedef detail::OutFStreamBase      Base;

    public:
        OutFStream() {}

        explicit
        OutFStream( char const* filename, ios_base::openmode mode = ios_base::out )
            : Base( filename, mode )
        {}

        explicit
        OutFStream( string const& filename, ios_base::openmode mode = ios_base::out )
            : Base( filename.c_str(), mode )
        {}

        explicit
        OutFStream( wchar_t const* filename, ios_base::openmode mode = ios_base::out )
            : Base( filename, mode )
        {}

        explicit
        OutFStream( wstring const& filename, ios_base::openmode mode = ios_base::out )
            : Base( filename.c_str(), mode )
        {}
    };
}  // namespace windows


Create a new paste based on this one


Comments: