00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2003--2007 Petter Urkedal <urkedal@nbi.dk> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CUOS_PATH_H 00019 #define CUOS_PATH_H 00020 00021 #include <cucon/fwd.h> 00022 #include <cu/str.h> 00023 00024 CU_BEGIN_DECLARATIONS 00025 /*!\defgroup cuos_path cuos/path.h: File path functions 00026 * @{ \ingroup cuos_mod 00027 * 00028 * Definition (normalised file name). A normalised file name is a string 00029 * subject to the following restrictions. The maximum substrings not 00030 * containing "/" are called components. Components of the form "", 00031 * "." and ".." are called special components. A file name is 00032 * either absolute or relative. An normalised absolute file name is 00033 * either "/", or starts with an empty component followed by one or 00034 * more non-special components. A normalised relative file name is either 00035 * ".", or it starts with zero or more "..", followed by zero or more 00036 * non-special components, but adding up to at least one component. 00037 * 00038 * <pre> 00039 * <i>NFN</i> ::= <i>relative_NFN</i> 00040 * | <i>absolute_NFN</i> 00041 * <i>relative_NFN</i> ::= "." 00042 * | "../"* ".." 00043 * | "../"* (<i>non_special_comp</i> "/")* <i>non_special_comp</i> 00044 * <i>absolute_NFN</i> ::= "/" 00045 * | ("/" <i>non_special_comp</i>)+ 00046 * </pre> 00047 */ 00048 00049 /*!True iff the string from \a s to \a s + \a len is a normalised file name. */ 00050 cu_bool_t cuos_is_path_charr(char const *s, size_t len); 00051 00052 /*!True iff \a s is a normalised file name. */ 00053 cu_bool_t cuos_is_path_cstr(char const *s); 00054 00055 /*!True iff \a str is a normalised file name. */ 00056 cu_bool_t cuos_is_path_str(cu_str_t str); 00057 00058 /*!Create normalised file names from the string from \a s to \a s + \a len 00059 * or \c NULL if it is not a valid file name. */ 00060 cu_str_t cuos_path_from_charr(char const *s, size_t len); 00061 00062 /*!Returns a normalised file name from \a s, or \c NULL if \a s does 00063 * not hold a valid file name. */ 00064 cu_str_t cuos_path_from_cstr(char const *s); 00065 00066 /*!Returns a normalised file name from \a str, or \c NULL if \a str does 00067 * not hold a valid file name. */ 00068 cu_str_t cuos_path_from_str(cu_str_t str); 00069 00070 /*!True iff the normalised file name \a path is absolute. */ 00071 cu_bool_t cuos_path_is_abs(cu_str_t path); 00072 00073 /*!True iff \a str is valid as a non-special path component. 00074 * \note It also returns false if the string contains ASCII non-printable 00075 * characters. It does not check non-ASCII (UTF-8 encoded) non-printables, 00076 * but this may change. Special path components are "." and "..". Beware 00077 * that some file systems may have others as well, which are not checked for 00078 * currently. */ 00079 cu_bool_t cuos_is_pathcomp_str(cu_str_t str); 00080 00081 /*!True iff the string from \a s to \a s + \a len is valid as a non-special 00082 * path component. See note under \ref cuos_is_pathcomp_str. */ 00083 cu_bool_t cuos_is_pathcomp_charr(char const *s, size_t len); 00084 00085 /*!True iff \a s is valid as a non-special path component. See note under 00086 * \ref cuos_is_pathcomp_str. */ 00087 cu_bool_t cuos_is_pathcomp_cstr(char const *s); 00088 00089 /*!Return the number of components of \a path, where "." counts as zero and 00090 * other components, including a leading "/" counts as one. */ 00091 int cuos_path_component_count(cu_str_t path); 00092 00093 /*!Returns the depth of \a path, where each non-special component and a 00094 * leading "/" counts as one, "." counts as zero, and ".." counts as -1. */ 00095 int cuos_path_depth(cu_str_t path); 00096 00097 /*!True iff \a path has no components, i.e. it is ".". This is faster 00098 * than using \ref cuos_path_component_count. */ 00099 CU_SINLINE cu_bool_t cuos_path_is_empty(cu_str_t path) 00100 { return cu_str_size(path) == 1 && cu_str_at(path, 0) == '.'; } 00101 00102 /** Given that \a path0 and \a path1 are normalised file names, if \a path1 is 00103 ** absolute, return \a path1, else return the normalised file name of \a path1 00104 ** relative to \a path0, i.e. the normalisation of the concatenation of (\a 00105 ** path0, "/", \a path1). \a path1 must be non-empty. */ 00106 cu_str_t cuos_path_cat2(cu_str_t path0, cu_str_t path1); 00107 00108 /** As \ref cuos_path_cat2 but with C string as second argument. */ 00109 cu_str_t cuos_path_cat2_sc(cu_str_t path0, char const *path1); 00110 00111 /** As \ref cuos_path_cat2 but with C string as first argument. */ 00112 cu_str_t cuos_path_cat2_cs(char const *path0, cu_str_t path1); 00113 00114 /** As \ref cuos_path_cat2 but with 2 C string arguments. */ 00115 cu_str_t cuos_path_cat2_cc(char const *path0, char const *path1); 00116 00117 cu_str_t cuos_path_cat3(cu_str_t path0, cu_str_t path1, cu_str_t path2); 00118 cu_str_t cuos_path_cat3_ssc(cu_str_t path0, cu_str_t path1, char const *path2); 00119 cu_str_t cuos_path_cat3_scs(cu_str_t path0, char const *path1, cu_str_t path2); 00120 cu_str_t cuos_path_cat3_css(char const *path0, cu_str_t path1, cu_str_t path2); 00121 cu_str_t cuos_path_cat3_ccc(char const *path0, char const *path1, 00122 char const *path2); 00123 00124 /*!\pre \a path is a normalised file name. 00125 * 00126 * If \a pos ≥ 0, then split \a path 00127 * before component \a pos and store the first and last parts as a 00128 * normalised file names in \c *path0 and \c *path1, respectively. If 00129 * \a pos < 0, the call is equivalent to one where \a pos is replaced by 00130 * \a n + \a pos, where \a n is the number of components. */ 00131 cu_bool_t cuos_path_split(cu_str_t path, int pos, 00132 cu_str_t *path0, cu_str_t *path1); 00133 00134 /*!Same as \a ret, where 00135 * \code cuos_path_split(path, -1, &ret, NULL)\endcode. */ 00136 cu_str_t cuos_path_dir(cu_str_t path); 00137 00138 /*!Same as \a ret, where 00139 * \code cuos_path_split(path, -1, NULL, &ret)\endcode. */ 00140 cu_str_t cuos_path_base(cu_str_t path); 00141 00142 /*!Returns extension of \a path, including the ".", or an empty string if 00143 * \a path has no extension. */ 00144 cu_str_t cuos_path_ext(cu_str_t path); 00145 00146 /*!Returns \a path without its extension or \a path itself if it has no 00147 * extension. */ 00148 cu_str_t cuos_path_sans_ext(cu_str_t path); 00149 00150 /*!True iff \a path ends with \a ext. */ 00151 cu_bool_t cuos_path_ext_eq(cu_str_t path, cu_str_t ext); 00152 00153 /*!True iff \a path ends with the substring from \a s to \a s + \a n. */ 00154 cu_bool_t cuos_path_ext_eq_charr(cu_str_t path, char const *s, size_t n); 00155 00156 /*!True iff \a path ends with \a ext. */ 00157 cu_bool_t cuos_path_ext_eq_cstr(cu_str_t path, char const *ext); 00158 00159 CU_END_DECLARATIONS 00160 00161 /** @} */ 00162 00163 #define cuos_path_join cuos_path_cat2 00164 #define cuos_path_join_str_cstr cuos_path_cat2_sc 00165 #define cuos_path_join_cstr_str cuos_path_cat2_cs 00166 #define cuos_path_join_2cstr cuos_path_cat2_cc 00167 00168 #endif