|
2 | 2 | #include <assert.h> |
3 | 3 | #include <ctype.h> |
4 | 4 | #include <stdbool.h> |
| 5 | +#include <stdint.h> |
5 | 6 | #include <stdlib.h> |
6 | 7 | #include <string.h> |
7 | 8 |
|
@@ -271,6 +272,75 @@ bool PathExists(const char *pPath) { |
271 | 272 | return pathExists; |
272 | 273 | } |
273 | 274 |
|
| 275 | +size_t ExtractLastPartOfPath(const char *const pPath, char *const pDestBuffer, |
| 276 | + size_t destBufferSize) { |
| 277 | + if (pPath == NULL || pDestBuffer == NULL || destBufferSize == 0) { |
| 278 | + return SIZE_MAX; |
| 279 | + } |
| 280 | + |
| 281 | + const size_t pathLenght = strnlen(pPath, MAX_PATH_LENGTH_WTH_TERMINATOR); |
| 282 | + if (pathLenght == 0 || pathLenght == MAX_PATH_LENGTH_WTH_TERMINATOR) { |
| 283 | + return SIZE_MAX; |
| 284 | + } |
| 285 | + |
| 286 | + if (pathLenght == 1 && (pPath[0] == '/' || pPath[0] == '\\')) { |
| 287 | + return SIZE_MAX; |
| 288 | + } |
| 289 | + |
| 290 | + char *pLocalPath = (char *)calloc(pathLenght + 1, sizeof(char)); |
| 291 | + memcpy(pLocalPath, pPath, pathLenght + 1); |
| 292 | + |
| 293 | + const char lastChar = pLocalPath[pathLenght - 1]; |
| 294 | + bool isDir = lastChar == '/' || lastChar == '\\'; |
| 295 | + |
| 296 | + if (isDir) { |
| 297 | + // Remove the last separator to make getting the file or directory name |
| 298 | + // more generic. |
| 299 | + pLocalPath[pathLenght - 1] = '\0'; |
| 300 | + } |
| 301 | + |
| 302 | + char *pLastForwardSeparator = strrchr(pLocalPath, '/'); |
| 303 | + char *pLastBackwardSeparator = strrchr(pLocalPath, '\\'); |
| 304 | + char *pLastSeparator = pLastForwardSeparator > pLastBackwardSeparator |
| 305 | + ? pLastForwardSeparator |
| 306 | + : pLastBackwardSeparator; |
| 307 | + |
| 308 | + size_t startIndexOfNameInPath = SIZE_MAX; |
| 309 | + char *pLastPart = NULL; |
| 310 | + |
| 311 | + if (pLastSeparator == NULL) { |
| 312 | + // No separator found, so the last part is the whole path. |
| 313 | + startIndexOfNameInPath = 0; |
| 314 | + pLastPart = pLocalPath; |
| 315 | + } else { |
| 316 | + startIndexOfNameInPath = (pLastSeparator - pLocalPath) + 1; |
| 317 | + pLastPart = pLastSeparator + 1; |
| 318 | + } |
| 319 | + |
| 320 | + if (isDir) { |
| 321 | + // Add the last separator back if it was removed. |
| 322 | + pLocalPath[pathLenght - 1] = lastChar; |
| 323 | + } |
| 324 | + |
| 325 | + const size_t lastPartLength = |
| 326 | + strnlen(pLastPart, MAX_PATH_LENGTH_WTH_TERMINATOR); |
| 327 | + |
| 328 | + if (lastPartLength == MAX_PATH_LENGTH_WTH_TERMINATOR) { |
| 329 | + free(pLocalPath); |
| 330 | + return SIZE_MAX; |
| 331 | + } |
| 332 | + |
| 333 | + if (lastPartLength >= destBufferSize) { |
| 334 | + free(pLocalPath); |
| 335 | + return SIZE_MAX; |
| 336 | + } |
| 337 | + |
| 338 | + memcpy(pDestBuffer, pLastPart, lastPartLength + 1); |
| 339 | + |
| 340 | + free(pLocalPath); |
| 341 | + return startIndexOfNameInPath; |
| 342 | +} |
| 343 | + |
274 | 344 | void OpenFileWithMode(FILE **pInFile, RaiiString *pFullPath, char *pOpenMode) { |
275 | 345 | *pInFile = fopen(pFullPath->pString, pOpenMode); |
276 | 346 | if (*pInFile == NULL) { |
|
0 commit comments