Is this too much code for a header only library?

Posted by Billy ONeal on Stack Overflow See other posts from Stack Overflow or by Billy ONeal
Published on 2010-04-07T19:14:47Z Indexed on 2010/04/07 19:23 UTC
Read the original article Hit count: 323

Filed under:
|
|
|

It seems like I had to inline quite a bit of code here. I'm wondering if it's bad design practice to leave this entirely in a header file like this:

#pragma once
#include <string>
#include <boost/noncopyable.hpp>
#include <boost/make_shared.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <Windows.h>
#include "../Exception.hpp"

namespace WindowsAPI { namespace FileSystem {

    class FileData;
    struct AllResults;
    struct FilesOnly;

    template <typename Filter_T = AllResults>
    class DirectoryIterator;

    namespace detail {
        class DirectoryIteratorImpl : public boost::noncopyable
        {
            WIN32_FIND_DATAW currentData;
            HANDLE hFind;
            std::wstring root;
        public:
            inline DirectoryIteratorImpl();
            inline explicit DirectoryIteratorImpl(const std::wstring& pathSpec);
            inline void increment();
            inline bool equal(const DirectoryIteratorImpl& other) const;
            inline const std::wstring& GetPathRoot() const;
            inline const WIN32_FIND_DATAW& GetCurrentFindData() const;
            inline ~DirectoryIteratorImpl();
        };
    }

    class FileData //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator.
    {
        boost::shared_ptr<detail::DirectoryIteratorImpl> iteratorSource;
    public:
        FileData(const boost::shared_ptr<detail::DirectoryIteratorImpl>& parent) : iteratorSource(parent) {};
        DWORD GetAttributes() const {
            return iteratorSource->GetCurrentFindData().dwFileAttributes;
        };
        bool IsDirectory() const {
            return (GetAttributes() | FILE_ATTRIBUTE_DIRECTORY) != 0;
        };
        bool IsFile() const {
            return !IsDirectory();
        };
        bool IsArchive() const {
            return (GetAttributes() | FILE_ATTRIBUTE_ARCHIVE) != 0;
        };
        bool IsReadOnly() const {
            return (GetAttributes() | FILE_ATTRIBUTE_READONLY) != 0;
        };
        unsigned __int64 GetSize() const {
            ULARGE_INTEGER intValue;
            intValue.LowPart = iteratorSource->GetCurrentFindData().nFileSizeLow;
            intValue.HighPart = iteratorSource->GetCurrentFindData().nFileSizeHigh;
            return intValue.QuadPart;
        };
        std::wstring GetFolderPath() const {
            return iteratorSource->GetPathRoot();
        };
        std::wstring GetFileName() const {
            return iteratorSource->GetCurrentFindData().cFileName;
        };
        std::wstring GetFullFileName() const {
            return GetFolderPath() + GetFileName();
        };
        std::wstring GetShortFileName() const {
            return iteratorSource->GetCurrentFindData().cAlternateFileName;
        };
        FILETIME GetCreationTime() const {
            return iteratorSource->GetCurrentFindData().ftCreationTime;
        };
        FILETIME GetLastAccessTime() const {
            return iteratorSource->GetCurrentFindData().ftLastAccessTime;
        };
        FILETIME GetLastWriteTime() const {
            return iteratorSource->GetCurrentFindData().ftLastWriteTime;
        };
    };

    struct AllResults : public std::unary_function<const FileData&, bool>
    {
        bool operator()(const FileData&) {
            return true;
        };
    }; 

    struct FilesOnly : public std::unary_function<const FileData&, bool>
    {
        bool operator()(const FileData& arg) {
            return arg.IsFile();
        };
    };

    template <typename Filter_T>
    class DirectoryIterator : public boost::iterator_facade<DirectoryIterator<Filter_T>, const FileData, std::input_iterator_tag>
    {
        friend class boost::iterator_core_access;
        boost::shared_ptr<detail::DirectoryIteratorImpl> impl;
        FileData current;
        Filter_T filter;
        void increment() {
            do {
                impl->increment();
            } while (! filter(current));
        };
        bool equal(const DirectoryIterator& other) const {
            return impl->equal(*other.impl);
        };
        const FileData& dereference() const {
            return current;
        };
    public:
        DirectoryIterator(Filter_T functor = Filter_T()) :
            impl(boost::make_shared<detail::DirectoryIteratorImpl>()),
            current(impl),
            filter(functor) {
        };
        explicit DirectoryIterator(const std::wstring& pathSpec, Filter_T functor = Filter_T()) :
            impl(boost::make_shared<detail::DirectoryIteratorImpl>(pathSpec)),
            current(impl),
            filter(functor) {
        };
    };

namespace detail {
    DirectoryIteratorImpl::DirectoryIteratorImpl() : hFind(INVALID_HANDLE_VALUE) {
    }

    DirectoryIteratorImpl::DirectoryIteratorImpl(const std::wstring& pathSpec) {
        std::wstring::const_iterator lastSlash =
            std::find(pathSpec.rbegin(), pathSpec.rend(), L'\\').base();
        root.assign(pathSpec.begin(), lastSlash);
        hFind = FindFirstFileW(pathSpec.c_str(), &currentData);
        if (hFind == INVALID_HANDLE_VALUE)
            WindowsApiException::ThrowFromLastError();
        while (!wcscmp(currentData.cFileName, L".") || !wcscmp(currentData.cFileName, L"..")) {
            increment();
        }
    }

    void DirectoryIteratorImpl::increment() {
        BOOL success =
            FindNextFile(hFind, &currentData);
        if (success)
            return;
        DWORD error = GetLastError();
        if (error == ERROR_NO_MORE_FILES) {
            FindClose(hFind);
            hFind = INVALID_HANDLE_VALUE;
        } else {
            WindowsApiException::Throw(error);
        }
    }

    DirectoryIteratorImpl::~DirectoryIteratorImpl() {
        if (hFind != INVALID_HANDLE_VALUE)
            FindClose(hFind);
    }

    bool DirectoryIteratorImpl::equal(const DirectoryIteratorImpl& other) const {
        if (this == &other)
            return true;
        return hFind == other.hFind;
    }

    const std::wstring& DirectoryIteratorImpl::GetPathRoot() const {
        return root;
    }

    const WIN32_FIND_DATAW& DirectoryIteratorImpl::GetCurrentFindData() const {
        return currentData;
    }
}

}}

© Stack Overflow or respective owner

Related posts about c++

Related posts about header-only