Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
path.c
00001 /** 00002 * @file path.c 00003 * @brief Path manipulation helper functions 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00024 * @version 1.7.6 00025 **/ 00026 00027 //Dependencies 00028 #include <string.h> 00029 #include <ctype.h> 00030 #include "path.h" 00031 00032 00033 /** 00034 * @brief Test if the path is absolute 00035 * @param[in] path NULL-terminated string that contains the path 00036 * @return TRUE is the path is absolute, else FALSE 00037 **/ 00038 00039 bool_t pathIsAbsolute(const char_t *path) 00040 { 00041 //Determine if the path is absolute or relative 00042 if(path[0] == '/' || path[0] == '\\') 00043 return TRUE; 00044 else 00045 return FALSE; 00046 } 00047 00048 00049 /** 00050 * @brief Test if the path is relative 00051 * @param[in] path NULL-terminated string that contains the path 00052 * @return TRUE is the path is relative, else FALSE 00053 **/ 00054 00055 bool_t pathIsRelative(const char_t *path) 00056 { 00057 //Determine if the path is absolute or relative 00058 if(path[0] == '/' || path[0] == '\\') 00059 return FALSE; 00060 else 00061 return TRUE; 00062 } 00063 00064 00065 /** 00066 * @brief Search a path for a file name 00067 * @param[in] path NULL-terminated string that contains the path to search 00068 * @return Pointer to the file name 00069 **/ 00070 00071 const char_t *pathFindFileName(const char_t *path) 00072 { 00073 size_t n; 00074 00075 //Retrieve the length of the path 00076 n = strlen(path); 00077 00078 //Skip trailing slash or backslash characters 00079 while(n > 0) 00080 { 00081 //Forward slash or backslash character found? 00082 if(path[n - 1] != '/' && path[n - 1] != '\\') 00083 break; 00084 00085 //Previous character 00086 n--; 00087 } 00088 00089 //Search the string for the last separator 00090 while(n > 0) 00091 { 00092 //Forward slash or backslash character found? 00093 if(path[n - 1] == '/' || path[n - 1] == '\\') 00094 break; 00095 00096 //Previous character 00097 n--; 00098 } 00099 00100 //Return a pointer to the file name 00101 return path + n; 00102 } 00103 00104 00105 /** 00106 * @brief Simplify a path 00107 * @param[in] path NULL-terminated string containing the path to be canonicalized 00108 **/ 00109 00110 void pathCanonicalize(char_t *path) 00111 { 00112 size_t i; 00113 size_t j; 00114 size_t k; 00115 00116 //Move to the beginning of the string 00117 i = 0; 00118 k = 0; 00119 00120 //Replace backslashes with forward slashes 00121 while(path[i] != '\0') 00122 { 00123 //Forward slash or backslash separator found? 00124 if(path[i] == '/' || path[i] == '\\') 00125 { 00126 path[k++] = '/'; 00127 while(path[i] == '/' || path[i] == '\\') i++; 00128 } 00129 else 00130 { 00131 path[k++] = path[i++]; 00132 } 00133 } 00134 00135 //Properly terminate the string with a NULL character 00136 path[k] = '\0'; 00137 00138 //Move back to the beginning of the string 00139 i = 0; 00140 j = 0; 00141 k = 0; 00142 00143 //Parse the entire string 00144 do 00145 { 00146 //Forward slash separator found? 00147 if(path[i] == '/' || path[i] == '\0') 00148 { 00149 //"." element found? 00150 if((i - j) == 1 && !strncmp(path + j, ".", 1)) 00151 { 00152 //Check whether the pathname is empty? 00153 if(k == 0) 00154 { 00155 if(path[i] == '\0') 00156 { 00157 path[k++] = '.'; 00158 } 00159 else if(path[i] == '/' && path[i + 1] == '\0') 00160 { 00161 path[k++] = '.'; 00162 path[k++] = '/'; 00163 } 00164 } 00165 else if(k > 1) 00166 { 00167 //Remove the final slash if necessary 00168 if(path[i] == '\0') 00169 k--; 00170 } 00171 } 00172 //".." element found? 00173 else if((i - j) == 2 && !strncmp(path + j, "..", 2)) 00174 { 00175 //Check whether the pathname is empty? 00176 if(k == 0) 00177 { 00178 path[k++] = '.'; 00179 path[k++] = '.'; 00180 00181 //Append a slash if necessary 00182 if(path[i] == '/') 00183 path[k++] = '/'; 00184 } 00185 else if(k > 1) 00186 { 00187 //Search the path for the previous slash 00188 for(j = 1; j < k; j++) 00189 { 00190 if(path[k - j - 1] == '/') 00191 break; 00192 } 00193 00194 //Slash separator found? 00195 if(j < k) 00196 { 00197 if(!strncmp(path + k - j, "..", 2)) 00198 { 00199 path[k++] = '.'; 00200 path[k++] = '.'; 00201 } 00202 else 00203 { 00204 k = k - j - 1; 00205 } 00206 00207 //Append a slash if necessary 00208 if(k == 0 && path[0] == '/') 00209 path[k++] = '/'; 00210 else if(path[i] == '/') 00211 path[k++] = '/'; 00212 } 00213 //No slash separator found? 00214 else 00215 { 00216 if(k == 3 && !strncmp(path, "..", 2)) 00217 { 00218 path[k++] = '.'; 00219 path[k++] = '.'; 00220 00221 //Append a slash if necessary 00222 if(path[i] == '/') 00223 path[k++] = '/'; 00224 } 00225 else if(path[i] == '\0') 00226 { 00227 k = 0; 00228 path[k++] = '.'; 00229 } 00230 else if(path[i] == '/' && path[i + 1] == '\0') 00231 { 00232 k = 0; 00233 path[k++] = '.'; 00234 path[k++] = '/'; 00235 } 00236 else 00237 { 00238 k = 0; 00239 } 00240 } 00241 } 00242 } 00243 else 00244 { 00245 //Copy directory name 00246 memmove(path + k, path + j, i - j); 00247 //Advance write pointer 00248 k += i - j; 00249 00250 //Append a slash if necessary 00251 if(path[i] == '/') 00252 path[k++] = '/'; 00253 } 00254 00255 //Move to the next token 00256 while(path[i] == '/') i++; 00257 j = i; 00258 } 00259 } while(path[i++] != '\0'); 00260 00261 //Properly terminate the string with a NULL character 00262 path[k] = '\0'; 00263 } 00264 00265 00266 /** 00267 * @brief Add a slash to the end of a string 00268 * @param[in,out] path NULL-terminated string that represents the path 00269 * @param[in] maxLen Maximum pathname length 00270 **/ 00271 00272 void pathAddSlash(char_t *path, size_t maxLen) 00273 { 00274 size_t n; 00275 00276 //Retrieve the length of the string 00277 n = strlen(path); 00278 00279 //Add a slash character only if necessary 00280 if(!n) 00281 { 00282 //Check the length of the resulting string 00283 if(maxLen >= 1) 00284 strcpy(path, "/"); 00285 } 00286 else if(path[n - 1] != '/' && path[n - 1] != '\\') 00287 { 00288 //Check the length of the resulting string 00289 if(maxLen >= (n + 1)) 00290 strcat(path, "/"); 00291 } 00292 } 00293 00294 00295 /** 00296 * @brief Remove the trailing slash from a given path 00297 * @param[in,out] path NULL-terminated string that contains the path 00298 **/ 00299 00300 void pathRemoveSlash(char_t *path) 00301 { 00302 char_t *end; 00303 00304 //Skip the leading slash character 00305 if(pathIsAbsolute(path)) 00306 path++; 00307 00308 //Search for the first slash character to be removed 00309 for(end = NULL; *path != '\0'; path++) 00310 { 00311 if(*path != '/' && *path != '\\') 00312 end = NULL; 00313 else if(!end) 00314 end = path; 00315 } 00316 00317 //Remove the trailing slash characters 00318 if(end) *end = '\0'; 00319 } 00320 00321 00322 /** 00323 * @brief Concatenate two paths 00324 * @param[in,out] path NULL-terminated string containing the first path 00325 * @param[in] more NULL-terminated string containing the second path 00326 * @param[in] maxLen Maximum pathname length 00327 **/ 00328 00329 void pathCombine(char_t *path, const char_t *more, size_t maxLen) 00330 { 00331 size_t n1; 00332 size_t n2; 00333 00334 //Append a slash character to the first path 00335 if(*path != '\0') 00336 pathAddSlash(path, maxLen); 00337 00338 //Skip any slash character at the beginning of the second path 00339 while(*more == '/' || *more == '\\') more++; 00340 00341 //Retrieve the length of the first path 00342 n1 = strlen(path); 00343 //Retrieve the length of second path 00344 n2 = strlen(more); 00345 00346 //Check the length of the resulting string 00347 if(n1 < maxLen) 00348 { 00349 //Limit the number of characters to be copied 00350 n2 = MIN(n2, maxLen - n1); 00351 //Concatenate the resulting string 00352 strncpy(path + n1, more, n2); 00353 //Properly terminate the string with a NULL character 00354 path[n1 + n2] = '\0'; 00355 } 00356 } 00357 00358 00359 /** 00360 * @brief Check whether a file name matches the specified pattern 00361 * @param[in] path NULL-terminated string that contains the path to be matched 00362 * @param[in] pattern NULL-terminated string that contains the pattern for 00363 * which to search. The pattern may contain wildcard characters 00364 * @return TRUE if the path matches the specified pattern, else FALSE 00365 **/ 00366 00367 bool_t pathMatch(const char_t *path, const char_t* pattern) 00368 { 00369 size_t i = 0; 00370 size_t j = 0; 00371 00372 //Parse the pattern string 00373 while(pattern[j] != '\0') 00374 { 00375 //Any wildcard character found? 00376 if(pattern[j] == '?') 00377 { 00378 //The question mark matches a single character 00379 if(path[i] == '\0') 00380 { 00381 return FALSE; 00382 } 00383 else 00384 { 00385 //Advance position in pathname 00386 i++; 00387 //Advance position in pattern string 00388 j++; 00389 } 00390 } 00391 else if(pattern[j] == '*') 00392 { 00393 //The asterisk sign matches zero or more characters 00394 if(path[i] == '\0') 00395 { 00396 //Advance position in pattern string 00397 j++; 00398 } 00399 else if(pathMatch(path + i, pattern + j + 1)) 00400 { 00401 return TRUE; 00402 } 00403 else 00404 { 00405 //Advance position in pathname 00406 i++; 00407 } 00408 } 00409 else 00410 { 00411 //Case insensitive comparison 00412 if(tolower((uint8_t) path[i]) != tolower((uint8_t) pattern[j])) 00413 { 00414 return FALSE; 00415 } 00416 else 00417 { 00418 //Advance position in pathname 00419 i++; 00420 //Advance position in pattern string 00421 j++; 00422 } 00423 } 00424 } 00425 00426 //Check whether the file name matches the specified pattern 00427 if(path[i] == '\0' && pattern[j] == '\0') 00428 return TRUE; 00429 else 00430 return FALSE; 00431 } 00432
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2