// Copyright (c) 2005-2008 Hartmut Kaiser // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef ADAPTORS_DEFAULT_FILE_COMMON_HELPERS_HPP #define ADAPTORS_DEFAULT_FILE_COMMON_HELPERS_HPP #include #include #include #ifndef MAX_PATH # define MAX_PATH _POSIX_PATH_MAX #endif /////////////////////////////////////////////////////////////////////////////// namespace detail { /////////////////////////////////////////////////////////////////////////// inline std::ios_base::openmode translate_open_mode (saga::filesystem::flags saga_mode) { int mode = std::ios::binary; if ( saga_mode & saga::filesystem::Read ) { mode |= std::ios::in; if ( saga_mode & saga::filesystem::Append ) { mode |= std::ios::ate; } } if ( saga_mode & saga::filesystem::Write ) { mode |= std::ios::out; if ( saga_mode & saga::filesystem::Append ) { mode |= std::ios::ate; } } if ( saga_mode & saga::filesystem::Binary ) { mode |= std::ios::binary; } if (saga_mode & saga::filesystem::Truncate) { mode |= std::ios::trunc; } return (std::ios_base::openmode) mode; } /////////////////////////////////////////////////////////////////////////// // wrapper for gethostname() inline std::string get_hostname() { char buffer[MAX_PATH] = { '\0' }; gethostname(buffer, sizeof(buffer)); return std::string(buffer); } /////////////////////////////////////////////////////////////////////////// inline std::string get_filepath(saga::url const& loc) { return loc.get_path(); } /////////////////////////////////////////////////////////////////////////// inline std::string get_scheme_authority(saga::url const& file_url) { std::string result (file_url.get_scheme()); if (!result.empty()) { result += ':'; } std::string authority (file_url.get_authority()); if (!authority.empty()) { result += "//"; result += authority; result += '/'; } return result; } #if defined(SAGA_DEFAULT_FILE_ADAPTOR_USE_CURL) /////////////////////////////////////////////////////////////////////////// inline saga::url complete_path(std::string root, std::string path) { namespace fs = boost::filesystem; saga::url root_url(root); saga::url path_url(path); if (root_url.get_scheme() != path_url.get_scheme() || root_url.get_authority() != path_url.get_authority()) { return path_url; // different hosts or schemes, use path as is } // same host and scheme, might be a relative path fs::path fs_path (get_filepath(path), fs::native); if (!fs_path.has_root_path()) { // path refers to a relative directory, generate an absolute name // using the given root fs::path fs_root (root_url.get_path(), fs::native); fs_root /= fs_path; root_url.set_scheme_specific_part(fs_root.get_path()); return root_url; } return path_url; // path refers to an absolute path, use as is } #endif /////////////////////////////////////////////////////////////////////////// inline bool file_islocal(saga::url const& file_url) { // we consider a file to be local if it's located on the local host std::string host(file_url.get_host()); if (!host.empty() && host != "localhost" && !boost::iequals(host, get_hostname())) return false; // remote files are not local // we consider a file to be local if it has no scheme at all or if the scheme // if file or any, given that the host is the local host std::string scheme(file_url.get_scheme()); return scheme.empty() || scheme == "file" || scheme == "any"; } /////////////////////////////////////////////////////////////////////////// inline bool file_ftp(saga::url const& file_url) { std::string scheme(file_url.get_scheme()); return scheme == "ftp" || scheme == "ftps"; } /////////////////////////////////////////////////////////////////////////// inline bool file_http(saga::url const& file_url) { std::string scheme(file_url.get_scheme()); return scheme == "http" || scheme == "https"; } // convert a SAGA pattern into a TR1::regex inline std::string regex_from_character_set(std::string::const_iterator& it, std::string::const_iterator end) { std::string::const_iterator start = it; std::string result(1, *it); // copy '[' if (*++it == '!') { result.append(1, '^'); // negated character set } else if (*it == ']') { SAGA_ADAPTOR_THROW_NO_CONTEXT( "Invalid pattern (empty character set) at: " + std::string(start, end), saga::NoSuccess); } else { result.append(1, *it); // append this character } // copy while in character set while (++it != end) { result.append(1, *it); if (*it == ']') break; } if (it == end || *it != ']') { SAGA_ADAPTOR_THROW_NO_CONTEXT( "Invalid pattern (missing closing ']') at: " + std::string(start, end), saga::NoSuccess); } return result; } inline std::string regex_from_string_choice(std::string::const_iterator& it, std::string::const_iterator end) { std::string::const_iterator start = it; std::string result(1, '('); // copy while in string choice bool has_one = false; while (++it != end && *it != '}') { if (*it == ',') { if (!has_one) { SAGA_ADAPTOR_THROW_NO_CONTEXT( "Invalid pattern (empty string alternative) at: " + std::string(start, end), saga::NoSuccess); } result.append(1, '|'); has_one = false; } else { result.append(1, *it); has_one = true; } } if (it == end || *it != '}') { SAGA_ADAPTOR_THROW_NO_CONTEXT( "Invalid pattern (missing closing '}') at: " + std::string(start, end), saga::NoSuccess); } result.append(1, ')'); return result; } inline std::string regex_from_pattern(std::string const& pattern) { std::string result; std::string::const_iterator end = pattern.end(); for (std::string::const_iterator it = pattern.begin(); it != end; ++it) { char c = *it; switch (c) { case '*': result.append(".*"); break; case '?': result.append(1, '.'); break; case '[': result.append(regex_from_character_set(it, end)); break; case '{': result.append(regex_from_string_choice(it, end)); break; case '\\': if (++it == end) { SAGA_ADAPTOR_THROW_NO_CONTEXT( "Invalid escape sequence at: " + pattern, saga::NoSuccess); } result.append(1, *it); break; default: result.append(1, c); break; } } return result; } /////////////////////////////////////////////////////////////////////////////// } // namespace detail #endif // !ADAPTORS_DEFAULT_FILE_COMMON_HELPERS_HPP