diff --git a/CMakeLists.txt b/CMakeLists.txt
index d9ad9cf..5be0652 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.9.2)
# set project name
project(cwalk
- VERSION 1.2.5
+ VERSION 1.2.7
DESCRIPTION "A simple path library"
LANGUAGES C)
@@ -175,6 +175,7 @@ if(ENABLE_TESTS)
create_test(DEFAULT normalize empty)
create_test(DEFAULT normalize only_separators)
create_test(DEFAULT normalize back_after_root)
+ create_test(DEFAULT normalize forward_slashes)
create_test(DEFAULT relative simple)
create_test(DEFAULT relative relative)
create_test(DEFAULT relative long_base)
@@ -191,6 +192,7 @@ if(ENABLE_TESTS)
create_test(DEFAULT relative check)
create_test(DEFAULT relative root_path_unix)
create_test(DEFAULT relative root_path_windows)
+ create_test(DEFAULT relative root_forward_slashes)
create_test(DEFAULT root absolute)
create_test(DEFAULT root unc)
create_test(DEFAULT root device_unc)
diff --git a/README.md b/README.md
index 6d9eec8..1cf4baf 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-[](https://travis-ci.org/likle/cwalk)
+[](https://travis-ci.com/likle/cwalk)
[](https://ci.appveyor.com/project/likle/cwalk)
[](https://codecov.io/gh/likle/cwalk)
[](https://lgtm.com/projects/g/likle/cwalk/context:cpp)
diff --git a/docs/reference/cwk_path_get_relative.md b/docs/reference/cwk_path_get_relative.md
index f9ccb56..f4477ac 100644
--- a/docs/reference/cwk_path_get_relative.md
+++ b/docs/reference/cwk_path_get_relative.md
@@ -64,8 +64,9 @@ The relative path is: ../world
## Changelog
-| Version | Description |
-|------------|--------------------------------------------------------|
-| **v1.2.5** | Fixed calls with path without segments. |
-| **v1.2.5** | Fixed calls with unequal roots in paths. |
-| **v1.0.0** | The function is introduced. |
+| Version | Description |
+|------------|---------------------------------------------------|
+| **v1.2.7** | Fixed windows paths with forward slashes in root. |
+| **v1.2.5** | Fixed calls with path without segments. |
+| **v1.2.5** | Fixed calls with unequal roots in paths. |
+| **v1.0.0** | The function is introduced. |
diff --git a/docs/reference/cwk_path_normalize.md b/docs/reference/cwk_path_normalize.md
index 0828850..03ded2c 100644
--- a/docs/reference/cwk_path_normalize.md
+++ b/docs/reference/cwk_path_normalize.md
@@ -68,6 +68,7 @@ Output:
## Changelog
-| Version | Description |
-|------------|--------------------------------------------------------|
-| **v1.0.0** | The function is introduced. |
\ No newline at end of file
+| Version | Description |
+|------------|---------------------------------------------------|
+| **v1.2.7** | Fixed windows paths with forward slashes in root. |
+| **v1.0.0** | The function is introduced. |
\ No newline at end of file
diff --git a/src/cwalk.c b/src/cwalk.c
index fe96c79..f681b52 100755
--- a/src/cwalk.c
+++ b/src/cwalk.c
@@ -124,7 +124,9 @@ static void cwk_path_terminate_output(char *buffer, size_t buffer_size,
static bool cwk_path_is_string_equal(const char *first, const char *second,
size_t first_size, size_t second_size)
{
- // THe two strings are not equal if the sizes are not equal.
+ bool are_both_separators;
+
+ // The two strings are not equal if the sizes are not equal.
if (first_size != second_size) {
return false;
}
@@ -140,11 +142,18 @@ static bool cwk_path_is_string_equal(const char *first, const char *second,
// own.
while (*first && *second && first_size > 0) {
// We can consider the string to be not equal if the two lowercase
- // characters are not equal.
- if (tolower(*first++) != tolower(*second++)) {
+ // characters are not equal. The two chars may also be separators, which
+ // means they would be equal.
+ are_both_separators = strchr(separators[path_style], *first) != NULL &&
+ strchr(separators[path_style], *second) != NULL;
+
+ if (tolower(*first) != tolower(*second) && !are_both_separators) {
return false;
}
+ first++;
+ second++;
+
--first_size;
}
@@ -482,7 +491,7 @@ static void cwk_path_get_root_windows(const char *path, size_t *length)
if (cwk_path_is_separator(c)) {
++c;
- // Check whether the path starts with a single back slash, which means this
+ // Check whether the path starts with a single backslash, which means this
// is not a network path - just a normal path starting with a backslash.
if (!cwk_path_is_separator(c)) {
// Okay, this is not a network path but we still use the backslash as a
@@ -570,6 +579,29 @@ static bool cwk_path_is_root_absolute(const char *path, size_t length)
return cwk_path_is_separator(&path[length - 1]);
}
+static void cwk_path_fix_root(char *buffer, size_t buffer_size, size_t length)
+{
+ size_t i;
+
+ // This only affects windows.
+ if (path_style != CWK_STYLE_WINDOWS) {
+ return;
+ }
+
+ // Make sure we are not writing further than we are actually allowed to.
+ if (length > buffer_size) {
+ length = buffer_size;
+ }
+
+ // Replace all forward slashes with backwards slashes. Since this is windows
+ // we can't have any forward slashes in the root.
+ for (i = 0; i < length; ++i) {
+ if (cwk_path_is_separator(&buffer[i])) {
+ buffer[i] = *separators[CWK_STYLE_WINDOWS];
+ }
+ }
+}
+
static size_t cwk_path_join_and_normalize_multiple(const char **paths,
char *buffer, size_t buffer_size)
{
@@ -584,8 +616,10 @@ static size_t cwk_path_join_and_normalize_multiple(const char **paths,
// later on whether we can remove superfluous "../" or not.
absolute = cwk_path_is_root_absolute(paths[0], pos);
- // First copy the root to the output. We will not modify the root.
+ // First copy the root to the output. After copying, we will normalize the
+ // root.
cwk_path_output_sized(buffer, buffer_size, 0, paths[0], pos);
+ cwk_path_fix_root(buffer, buffer_size, pos);
// So we just grab the first segment. If there is no segment we will always
// output a "/", since we currently only support absolute paths here.
diff --git a/test/normalize_test.c b/test/normalize_test.c
index 4ab4c25..508c9d6 100644
--- a/test/normalize_test.c
+++ b/test/normalize_test.c
@@ -6,6 +6,25 @@
#include
#include
+int normalize_forward_slashes()
+{
+ size_t count;
+ char result[FILENAME_MAX];
+ char *input, *expected;
+
+ cwk_path_set_style(CWK_STYLE_WINDOWS);
+
+ input = "C:/this/is/a/test/path";
+ strcpy(result, input);
+ expected = "C:\\this\\is\\a\\test\\path";
+ count = cwk_path_normalize(result, result, sizeof(result));
+ if (count != strlen(expected) || strcmp(result, expected) != 0) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
int normalize_back_after_root()
{
size_t count;
diff --git a/test/relative_test.c b/test/relative_test.c
index 9fceb50..2303738 100755
--- a/test/relative_test.c
+++ b/test/relative_test.c
@@ -6,6 +6,26 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+int relative_root_forward_slashes()
+{
+ char result[FILENAME_MAX];
+ size_t length;
+
+ cwk_path_set_style(CWK_STYLE_WINDOWS);
+
+ length = cwk_path_get_relative("C:\\foo\\bar\\baz\\", "C:/foo/bar/file.txt",
+ result, sizeof(result));
+ if (length != 11) {
+ return EXIT_FAILURE;
+ }
+
+ if (strcmp(result, "..\\file.txt") != 0) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
int relative_root_path_windows()
{
char result[FILENAME_MAX];