forked from bkaradzic/bx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
451 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright 2010-2017 Branimir Karadzic. All rights reserved. | ||
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause | ||
*/ | ||
|
||
#ifndef BX_FILEPATH_H_HEADER_GUARD | ||
#define BX_FILEPATH_H_HEADER_GUARD | ||
|
||
#include "string.h" | ||
|
||
namespace bx | ||
{ | ||
const int32_t kMaxFilePath = 1024; | ||
|
||
/// FilePath parser and helper. | ||
/// | ||
/// /abv/gd/555/333/pod.mac | ||
/// ppppppppppppppppbbbeeee | ||
/// ^ ^ ^ | ||
/// +-path base-+ +-ext | ||
/// ^^^^^^^ | ||
/// +-filename | ||
/// | ||
class FilePath | ||
{ | ||
public: | ||
/// | ||
FilePath(); | ||
|
||
/// | ||
FilePath(const StringView& _str); | ||
|
||
/// | ||
void set(const StringView& _str); | ||
|
||
/// | ||
const StringView get() const; | ||
|
||
/// If path is `/abv/gd/555/333/pod.mac` returns `/abv/gd/555/333/`. | ||
/// | ||
const StringView getPath() const; | ||
|
||
/// If path is `/abv/gd/555/333/pod.mac` returns `pod.mac`. | ||
/// | ||
const StringView getFileName() const; | ||
|
||
/// If path is `/abv/gd/555/333/pod.mac` returns `pod`. | ||
/// | ||
const StringView getBaseName() const; | ||
|
||
/// If path is `/abv/gd/555/333/pod.mac` returns `.mac`. | ||
/// | ||
const StringView getExt() const; | ||
|
||
/// | ||
bool isAbsolute() const; | ||
|
||
private: | ||
char m_filePath[kMaxFilePath]; | ||
}; | ||
|
||
} // namespace bx | ||
|
||
#endif // BX_FILEPATH_H_HEADER_GUARD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/* | ||
* Copyright 2010-2017 Branimir Karadzic. All rights reserved. | ||
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause | ||
*/ | ||
|
||
#include <bx/filepath.h> | ||
#include <bx/readerwriter.h> | ||
|
||
namespace bx | ||
{ | ||
static bool isPathSeparator(char _ch) | ||
{ | ||
return false | ||
|| '/' == _ch | ||
|| '\\' == _ch | ||
; | ||
} | ||
|
||
static int32_t normalizeFilePath(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) | ||
{ | ||
// Reference: Lexical File Names in Plan 9 or Getting Dot-Dot Right | ||
// https://9p.io/sys/doc/lexnames.html | ||
|
||
const int32_t num = strLen(_src, _num); | ||
|
||
if (0 == num) | ||
{ | ||
return strCopy(_dst, _dstSize, "."); | ||
} | ||
|
||
int32_t size = 0; | ||
|
||
StaticMemoryBlockWriter writer(_dst, _dstSize); | ||
Error err; | ||
|
||
int32_t idx = 0; | ||
int32_t dotdot = 0; | ||
|
||
if (2 <= num | ||
&& ':' == _src[1]) | ||
{ | ||
size += write(&writer, toUpper(_src[idx]), &err); | ||
size += write(&writer, ':', &err); | ||
idx += 2; | ||
dotdot = size; | ||
} | ||
|
||
const int32_t slashIdx = idx; | ||
|
||
bool rooted = isPathSeparator(_src[idx]); | ||
if (rooted) | ||
{ | ||
size += write(&writer, '/', &err); | ||
++idx; | ||
dotdot = size; | ||
} | ||
|
||
while (idx < num && err.isOk() ) | ||
{ | ||
switch (_src[idx]) | ||
{ | ||
case '/': | ||
case '\\': | ||
++idx; | ||
break; | ||
|
||
case '.': | ||
if (idx+1 == num | ||
|| isPathSeparator(_src[idx+1]) ) | ||
{ | ||
++idx; | ||
break; | ||
} | ||
|
||
if ('.' == _src[idx+1] | ||
&& (idx+2 == num || isPathSeparator(_src[idx+2]) ) ) | ||
{ | ||
idx += 2; | ||
|
||
if (dotdot < size) | ||
{ | ||
for (--size | ||
; dotdot < size && !isPathSeparator(_dst[size]) | ||
; --size) | ||
{ | ||
} | ||
seek(&writer, size, Whence::Begin); | ||
} | ||
else if (!rooted) | ||
{ | ||
if (0 < size) | ||
{ | ||
size += write(&writer, '/', &err); | ||
} | ||
|
||
size += write(&writer, "..", &err); | ||
dotdot = size; | ||
} | ||
|
||
break; | ||
} | ||
|
||
BX_FALLTHROUGH; | ||
|
||
default: | ||
if ( ( rooted && slashIdx+1 != size) | ||
|| (!rooted && 0 != size) ) | ||
{ | ||
size += write(&writer, '/', &err); | ||
} | ||
|
||
for (; idx < num && !isPathSeparator(_src[idx]); ++idx) | ||
{ | ||
size += write(&writer, _src[idx], &err); | ||
} | ||
|
||
break; | ||
} | ||
} | ||
|
||
if (0 == size) | ||
{ | ||
size += write(&writer, '.', &err); | ||
} | ||
|
||
write(&writer, '\0', &err); | ||
|
||
return size; | ||
} | ||
|
||
FilePath::FilePath() | ||
{ | ||
set(""); | ||
} | ||
|
||
FilePath::FilePath(const StringView& _filePath) | ||
{ | ||
set(_filePath); | ||
} | ||
|
||
void FilePath::set(const StringView& _filePath) | ||
{ | ||
normalizeFilePath( | ||
m_filePath | ||
, BX_COUNTOF(m_filePath) | ||
, _filePath.getPtr() | ||
, _filePath.getLength() | ||
); | ||
} | ||
|
||
const StringView FilePath::get() const | ||
{ | ||
return StringView(m_filePath); | ||
} | ||
|
||
const StringView FilePath::getPath() const | ||
{ | ||
const char* end = strRFind(m_filePath, '/'); | ||
if (NULL != end) | ||
{ | ||
return StringView(m_filePath, end+1); | ||
} | ||
|
||
return StringView(); | ||
} | ||
|
||
const StringView FilePath::getFileName() const | ||
{ | ||
const char* fileName = strRFind(m_filePath, '/'); | ||
if (NULL != fileName) | ||
{ | ||
return StringView(fileName+1); | ||
} | ||
|
||
return get(); | ||
} | ||
|
||
const StringView FilePath::getBaseName() const | ||
{ | ||
const StringView fileName = getFileName(); | ||
if (!fileName.isEmpty() ) | ||
{ | ||
const char* ext = strFind(fileName.getPtr(), '.', fileName.getLength() ); | ||
if (ext != NULL) | ||
{ | ||
return StringView(fileName.getPtr(), ext); | ||
} | ||
} | ||
|
||
return StringView(); | ||
} | ||
|
||
const StringView FilePath::getExt() const | ||
{ | ||
const StringView fileName = getFileName(); | ||
if (!fileName.isEmpty() ) | ||
{ | ||
const char* ext = strFind(fileName.getPtr(), '.', fileName.getLength() ); | ||
return StringView(ext); | ||
} | ||
|
||
return StringView(); | ||
} | ||
|
||
bool FilePath::isAbsolute() const | ||
{ | ||
return '/' == m_filePath[0] // no drive letter | ||
|| (':' == m_filePath[1] && '/' == m_filePath[2]) // with drive letter | ||
; | ||
} | ||
|
||
} // namespace bx |
Oops, something went wrong.