This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| File Path Code Submitted by

I wrote this source because nearly every program I wrote had to do some sort of file path (be it a local file or URL) manipulation. It's not quite done yet, because you can't change the directory yet. I also plan to add functions that will resolve relative paths with respect to absolute paths.
filepath.hpp is the header file which contains the definition of class basic_filepath<>. test.cpp is an example of using the class.
If you didn't notice, this code is designed similarly to the Standard C++ Library.
This code is 100% public domain. Take it and use it however you wish. :)
One last thing... This code won't compile in Visual C++. You need a good C++ compiler to use it. It even has a little bit of hackery so it will compile correctly with gcc...
--
Chad Austin (AegisKnight)
http://www.nerv-un.net/~aegis/

Currently browsing [filepath.zip] (2,905 bytes) - [test.cpp] - (1,020 bytes)

    #include <iostream>
    #include <string>
    #include "filepath.hpp"
    using namespace std;
    using namespace fp;

    int main()
    {
        string path;
        cout << "Enter path: ";
        cin >> path;

        filepath fp = path.c_str();
        cout << "Path: " << fp.str() << endl;
        cout << "is_absolute: " << fp.is_absolute() << endl;

        cout << "is_url: " << fp.is_url() << endl;
        if (fp.is_url()) {
            cout << "\tscheme: " << fp.get_scheme() << endl;
            cout << "\tserver: " << fp.get_server() << endl;
            cout << "\tport:   " << fp.get_port()   << endl;
            cout << "\tquery:  " << fp.get_query()  << endl;
        }

        cout << "is_windows: " << fp.is_windows() << endl;
        if (fp.is_windows()) {
            cout << "\tdrive: " << fp.get_drive() << endl;
        }

        cout << "path:      " << fp.get_path()      << endl;
        cout << "file:      " << fp.get_file()      << endl;
        cout << "extension: " << fp.get_extension() << endl;

        // required for VC++
        return 0;
    }

Currently browsing [filepath.zip] (2,905 bytes) - [filepath.hpp] - (12,231 bytes)

    // filepath.hpp
    // Chad Austin -- aegis@nerv-un.net
    // http://www.nerv-un.net/~aegis/
    // 2000.07.14
    //
    // path_delim<T> class
    // file_path<T> class

    #ifdef _MSC_VER
    #pragma warning(disable : 4786)  // identifier too long
    #endif

    #ifndef FILEPATH_HPP
    #define FILEPATH_HPP

    #include <sstream>
    #include <list>
    #include <string>
    #include <locale>
    #include <cstdlib>

    namespace fp
    {

        // path_delimiters<charT>
        template<typename charT>
        class path_delimiters
        {
        public:
            static bool is_path_delim(charT c);
            static bool is_drive_delim(charT c);
            static bool is_scheme_delim(charT c);
            static bool is_port_delim(charT c);
            static bool is_query_delim(charT c);
            static bool is_extension_delim(charT c);

            static charT path_delim();
            static charT drive_delim();
            static charT scheme_delim();
            static charT port_delim();
            static charT query_delim();
            static charT extension_delim();

            static const charT* unknown_scheme();
        };

        // path_delimiters<char>
        template<>
        class path_delimiters<char>
        {
        public:
            static bool is_path_delim(charT c)      { return (c == '/') || (c == '\\'); }
            static bool is_drive_delim(charT c)     { return (c == ':'); }
            static bool is_scheme_delim(charT c)    { return (c == ':'); }
            static bool is_port_delim(charT c)      { return (c == ':'); }
            static bool is_query_delim(charT c)     { return (c == '?'); }
            static bool is_extension_delim(charT c) { return (c == '.'); }

            static charT path_delim()      { return '/'; }
            static charT drive_delim()     { return ':'; }
            static charT scheme_delim()    { return ':'; }
            static charT port_delim()      { return ':'; }
            static charT query_delim()     { return '?'; }
            static charT extension_delim() { return '.'; }

            static const charT* unknown_scheme() { return "unknown"; }
        };

        // path_delimiters<wchar_t>
        template<>
        class path_delimiters<wchar_t>
        {
        public:
            static bool is_path_delim(charT c)      { return (c == L'/') || (c == L'\\'); }
            static bool is_drive_delim(charT c)     { return (c == L':'); }
            static bool is_scheme_delim(charT c)    { return (c == L':'); }
            static bool is_port_delim(charT c)      { return (c == L':'); }
            static bool is_query_delim(charT c)     { return (c == L'?'); }
            static bool is_extension_delim(charT c) { return (c == L'.'); }

            static charT path_delim()      { return L'/'; }
            static charT drive_delim()     { return L':'; }
            static charT scheme_delim()    { return L':'; }
            static charT port_delim()      { return L':'; }
            static charT query_delim()     { return L'?'; }
            static charT extension_delim() { return L'.'; }

            static const charT* unknown_scheme() { return L"unknown"; }
        };

        // basic_filepath<charT, delimT>
        template<typename charT, typename delimT = path_delimiters<charT> >
        class basic_filepath
        {
        public:
            typedef std::basic_string<charT> string;

            // constructors

            basic_filepath() {
                // empty path
                parse(string().c_str());
            }

            basic_filepath(const charT* path) {
                parse(path);
            }

            // operator overloads
            basic_filepath<charT, delimT>&
            operator=(const basic_filepath<charT, delimT>& rhs) {
                if (this != &rhs) {
                    parse(rhs.str().c_str());
                }
            }

            // stringify
            string str() const {
                basic_ostringstream<charT> s;

                // add URL elements
                if (is_url()) {
                    s << m_scheme;
                    s << delimT::scheme_delim();
                    s << delimT::path_delim();
                    s << delimT::path_delim();
                    s << m_server;
                    if (m_port != 0) {
                        s << delimT::port_delim();
                        s << m_port;
                    }
                }

                // add Windows elements
                if (is_windows()) {
                    s << m_drive;
                    s << delimT::drive_delim();
                }

                // add leading path delimiter if absolute
                if (m_is_absolute) {
                    s << delimT::path_delim();
                }

                // add directories
                for (std::list<string>::const_iterator i = m_path_segments.begin();
                     i != m_path_segments.end();
                     i++) {
                    s << *i << delimT::path_delim();
                }

                // add file and extension
                if (m_file.length() > 0) {
                    s << m_file;
                    if (m_extension.length() > 0) {
                        s << delimT::extension_delim() << m_extension;
                    }
                }

                // final URL elements
                if (is_url() && m_query.length() > 0) {
                    s << delimT::query_delim() << m_query;
                }

                return s.str();
            }

            // Windows/DOS

            bool is_windows() const {
                return (m_drive != charT());
            }

            void set_drive(charT drive) const {
                m_drive = drive;
            }

            charT get_drive() const {
                return m_drive;
            }

            // URL

            bool is_url() const {
                return (m_scheme.length() != 0);
            }

            void set_scheme(const string& scheme) {
                m_scheme = scheme;
            }

            string get_scheme() const {
                return m_scheme;
            }

            void set_server(const string& server) {
                if (is_url() == false) {
                    m_scheme = delimT::unknown_scheme();
                }
                m_server = server;
            }

            string get_server() const {
                return m_server;
            }

            void set_port(int port) {
                if (is_url() == false) {
                    m_scheme = delimT::unknown_scheme();
                }
                m_port = port;
            }

            int get_port() const {
                return m_port;
            }

            void set_query(const string& query) {
                if (is_url() == false) {
                    m_scheme = delimT::unknown_scheme();
                }
                m_query = query;
            }

            string get_query() const {
                return m_query;
            }

            // general

            bool is_absolute() const {
                return m_is_absolute;
            }

            string get_path() const {
                string r;
                if (m_is_absolute) {
                    r = delimT::path_delim();
                }

                for (std::list<string>::const_iterator i = m_path_segments.begin();
                     i != m_path_segments.end();
                     i++) {
                    r += *i;
                    r += delimT::path_delim();
                }
                return r;
            }

            bool has_file() const {
                return (m_file.length() != 0);
            }

            void set_file(const string& file) {
                m_file = file;
            }

            string get_file() const {
                return m_file;
            }

            void set_extension(const string& extension) {
                m_extension = extension;
            }

            string get_extension() {
                return m_extension;
            }

        private:
            void parse(const charT* s) {
                // initialize
                m_is_absolute = false;
                m_drive = charT();
                m_scheme = string();
                m_server = string();
                m_port = 0;
                m_query = string();
                m_path_segments.clear();
                m_file = string();
                m_extension = string();

                // check for Windows path first
                if (std::isalpha(s[0], std::locale::empty()) &&
                        delimT::is_drive_delim(s[1]) &&
                        delimT::is_path_delim(s[2])) {
                    m_drive = s[0];
                    m_is_absolute = true;
                    s += 3;
                }

                const charT* p = s;

                if (!is_windows()) {
                    // check for URL
                    while (*p) {
                        if (delimT::is_scheme_delim(*p)) {
                            m_scheme = string(s, p - s);
                            s = p + 1;

                            // possibly skip the next two path delimiters
                            if (delimT::is_path_delim(*s)) {
                                s++;
                            }
                            if (delimT::is_path_delim(*s)) {
                                s++;
                            }
                            break;
                        }
                        p++;
                    }

                    // if we found a URL, parse server/port
                    if (m_scheme.length() > 0) {

                        // server
                        while (*s) {
                            if (delimT::is_port_delim(*s) ||
                                delimT::is_path_delim(*s)) {
                                break;
                            }
                            m_server += *s;
                            s++;
                        }

                        // port
                        if (delimT::is_port_delim(*s)) {
                            s++;
                            string port;
                            while (*s && !delimT::is_path_delim(*s)) {
                                port += *s;
                                s++;
                            }

                            basic_istringstream<charT> is(port);
                            is >> m_port;
                        }
                    }
                }

                // parse path list
                string c;
                while (*s) {
                    // if it's a path delimiter, add it to the path list
                    if (delimT::is_path_delim(*s)) {
                        if (c.length() > 0) {
                            m_path_segments.push_back(c);
                        } else {
                            // if first segment is empty
                            // (first path character is /),
                            // path is absolute
                            if (m_path_segments.size() == 0) {
                                m_is_absolute = true;
                            }
                        }
                        c = string();
                        s++;
                        continue;
                    }

                    c += *s;
                    s++;
                }

                // parse filename in c
                const charT* q = c.c_str();
                p = q;
                while (*p) {
                    if (delimT::is_query_delim(*p)) {
                        // grab the query string
                        m_query = p + 1;
                        break;
                    }
                    p++;
                }

                // get a file+extension string
                string file(q, p - q);
                int pos = -1;
                for (int i = file.length() - 1; i >= 0; i--) {
                    if (delimT::is_extension_delim(file[i])) {
                        pos = i;
                        break;
                    }
                }

                if (pos == -1) {
                    m_file = file;
                } else {
                    m_file = file.substr(0, pos);
                    m_extension = file.substr(pos + 1, file.length() - pos - 1);
                }
            }

        private:
            bool m_is_absolute;

            // windows
            charT m_drive;

            // URL
            string m_scheme;
            string m_server;
            int    m_port;
            string m_query;

            // general
            std::list<string> m_path_segments;
            string m_file;
            string m_extension;
        };

        typedef basic_filepath<char>    filepath;
        typedef basic_filepath<wchar_t> wfilepath;

    } // end namespace

    #endif // FILEPATH_HPP

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.