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.