Author SHA1 Message Date
Daniel Greenstein 8c0f1738fc accepting fix proposed in issue #20 - for deadlock in path split when the path ends in a double slash 2019-03-04 02:20:11 +00:00
Danny Greenstein 20dac44746 Merge pull request #23 from grdanny/abspath-tests-for-both-nt-and-posix
testing both posix and nt version of the abspath call
2019-02-25 22:30:16 -08:00
Daniel Greenstein 3670fab511 testing both posix and nt version of the abspath call 2019-02-24 19:01:53 +00:00
Jeremy Selan c2de99deb4 fix replace on empty strings 2012-10-16 14:31:17 -07:00
Jeremy Selan f38e93591b fix rsplit for non-space characters 2012-10-16 14:30:43 -07:00
Jeremy Selan 9dc73e8533 switch ssize_t -> Py_ssize_t for windows friendliness 2012-04-13 10:19:29 -07:00
Jeremy Selan ae50dda1ea exposed all os::path posix vs. nt varients 2012-04-10 17:05:23 -07:00
Jeremy Selan a5c3cfa274 do_strip windows bugfix
switched to use ssize_t (signed) for internal counters, to match the python
source.  (see Modules/stropmodule.c : do_strip)

This addresses a bug uncovered by Laszlo Sebo on Windows, when stripping an
empty string.
2012-04-10 16:29:12 -07:00
Jeremy Selan 6c7eadc6c2 added os::path::abspath 2011-10-25 10:52:49 -07:00
3 changed files with 629 additions and 151 deletions
+87 -148
View File
@@ -202,7 +202,7 @@ typedef int Py_ssize_t;
{
if ( maxsplit < 0 )
{
split( str, result, sep, 0 );
split( str, result, sep, maxsplit );
return;
}
@@ -214,11 +214,11 @@ typedef int Py_ssize_t;
return;
}
std::string::size_type i,j, len = str.size(), n = sep.size();
Py_ssize_t i,j, len = (Py_ssize_t) str.size(), n = (Py_ssize_t) sep.size();
i = j = len;
while ( i > n )
while ( i >= n )
{
if ( str[i - 1] == sep[n - 1] && str.substr( i - n, n ) == sep )
{
@@ -249,7 +249,7 @@ typedef int Py_ssize_t;
///
std::string do_strip( const std::string & str, int striptype, const std::string & chars )
{
std::string::size_type len = str.size(), i, j, charslen = chars.size();
Py_ssize_t len = (Py_ssize_t) str.size(), i, j, charslen = (Py_ssize_t) chars.size();
if ( charslen == 0 )
{
@@ -967,6 +967,7 @@ typedef int Py_ssize_t;
//////////////////////////////////////////////////////////////////////////////////////////////
///
///
std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count )
{
int sofar = 0;
@@ -974,8 +975,10 @@ typedef int Py_ssize_t;
std::string s( str );
std::string::size_type oldlen = oldstr.size(), newlen = newstr.size();
cursor = find( s, oldstr, cursor );
while ( ( cursor = find( s, oldstr, cursor ) ) != -1 )
while ( cursor != -1 && cursor <= (int)s.size() )
{
if ( count > -1 && sofar >= count )
{
@@ -983,15 +986,25 @@ typedef int Py_ssize_t;
}
s.replace( cursor, oldlen, newstr );
cursor += (int) newlen;
if ( oldlen != 0)
{
cursor = find( s, oldstr, cursor );
}
else
{
++cursor;
}
++sofar;
}
return s;
}
//////////////////////////////////////////////////////////////////////////////////////////////
///
///
@@ -1128,6 +1141,34 @@ namespace path
}
//////////////////////////////////////////////////////////////////////////////////////////////
///
///
std::string abspath_nt(const std::string & path, const std::string & cwd)
{
std::string p = path;
if(!isabs_nt(p)) p = join_nt(cwd, p);
return normpath_nt(p);
}
std::string abspath_posix(const std::string & path, const std::string & cwd)
{
std::string p = path;
if(!isabs_posix(p)) p = join_posix(cwd, p);
return normpath_posix(p);
}
std::string abspath(const std::string & path, const std::string & cwd)
{
#ifdef WINDOWS
return abspath_nt(path, cwd);
#else
return abspath_posix(path, cwd);
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////
///
///
@@ -1306,7 +1347,8 @@ namespace path
// set i to index beyond p's last slash
int i = (int)p.size();
// walk back to find the index of the first slash from the end
while(i>0 && (p[i-1] != '\\') && (p[i-1] != '/'))
{
i = i - 1;
@@ -1320,7 +1362,7 @@ namespace path
while(!head2.empty() && ((pystring::slice(head2,-1) == "/") ||
(pystring::slice(head2,-1) == "\\")))
{
head2 = pystring::slice(head,0,-1);
head2 = pystring::slice(head2,0,-1);
}
if(!head2.empty()) head = head2;
@@ -1360,19 +1402,51 @@ namespace path
///
///
std::string basename(const std::string & path)
std::string basename_nt(const std::string & path)
{
std::string head, tail;
split(head, tail, path);
split_nt(head, tail, path);
return tail;
}
std::string dirname(const std::string & path)
std::string basename_posix(const std::string & path)
{
std::string head, tail;
split(head, tail, path);
split_posix(head, tail, path);
return tail;
}
std::string basename(const std::string & path)
{
#ifdef WINDOWS
return basename_nt(path);
#else
return basename_posix(path);
#endif
}
std::string dirname_nt(const std::string & path)
{
std::string head, tail;
split_nt(head, tail, path);
return head;
}
std::string dirname_posix(const std::string & path)
{
std::string head, tail;
split_posix(head, tail, path);
return head;
}
std::string dirname(const std::string & path)
{
#ifdef WINDOWS
return dirname_nt(path);
#else
return dirname_posix(path);
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -1590,138 +1664,3 @@ namespace path
}//namespace pystring
#ifdef PYSTRING_UNITTEST
#include "unittest.h"
PYSTRING_ADD_TEST(pystring_os_path, splitdrive)
{
using namespace pystring::os::path;
std::string drivespec, pathspec;
splitdrive_posix(drivespec, pathspec, "/Users/test"); PYSTRING_CHECK_EQUAL(drivespec, ""); PYSTRING_CHECK_EQUAL(pathspec, "/Users/test");
splitdrive_nt(drivespec, pathspec, "C:\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "C:" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
splitdrive_nt(drivespec, pathspec, "\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
}
PYSTRING_ADD_TEST(pystring_os_path, isabs)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(isabs_posix("/Users/test"), true );
PYSTRING_CHECK_EQUAL(isabs_posix("\\Users\\test"), false);
PYSTRING_CHECK_EQUAL(isabs_posix("../Users"), false);
PYSTRING_CHECK_EQUAL(isabs_posix("Users"), false);
PYSTRING_CHECK_EQUAL(isabs_nt("C:\\Users\\test"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("C:/Users"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("/Users"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("../Users"), false);
PYSTRING_CHECK_EQUAL(isabs_nt("..\\Users"), false);
}
PYSTRING_ADD_TEST(pystring_os_path, join)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(join_posix("a","b"), "a/b" );
PYSTRING_CHECK_EQUAL(join_posix("/a","b"), "/a/b" );
PYSTRING_CHECK_EQUAL(join_posix("/a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("//a","b"), "//a/b" );
PYSTRING_CHECK_EQUAL(join_posix("//a","b//"), "//a/b//" );
PYSTRING_CHECK_EQUAL(join_posix("../a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("../a","b"), "../a/b" );
std::vector< std::string > paths;
PYSTRING_CHECK_EQUAL(join_posix(paths), "" );
paths.push_back("/a");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a" );
paths.push_back("b");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b" );
paths.push_back("c/");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/" );
paths.push_back("d");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/d" );
paths.push_back("/e");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/e" );
PYSTRING_CHECK_EQUAL(join_nt("c:","/a"), "c:/a" );
PYSTRING_CHECK_EQUAL(join_nt("c:/","/a"), "c:/a" );
PYSTRING_CHECK_EQUAL(join_nt("c:/a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_nt("c:","d:/"), "d:/" );
PYSTRING_CHECK_EQUAL(join_nt("c:/","d:/"), "d:/" );
PYSTRING_CHECK_EQUAL(join_nt("a","b"), "a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("\\a","b"), "\\a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","b"), "c:\\a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","c:\\b"), "c:\\b" );
PYSTRING_CHECK_EQUAL(join_nt("..\\a","b"), "..\\a\\b" );
}
PYSTRING_ADD_TEST(pystring_os_path, normpath)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(normpath_posix("A//B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("A/./B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("A/foo/../B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("/A//B"), "/A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("//A//B"), "//A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("///A//B"), "/A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("../A"), "../A" );
PYSTRING_CHECK_EQUAL(normpath_posix("../A../"), "../A.." );
PYSTRING_CHECK_EQUAL(normpath_posix("FOO/../A../././B"), "A../B" );
PYSTRING_CHECK_EQUAL(normpath_nt(""), "." );
PYSTRING_CHECK_EQUAL(normpath_nt("A"), "A" );
PYSTRING_CHECK_EQUAL(normpath_nt("A./B"), "A.\\B" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\"), "C:\\" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\"), "C:\\A.." );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\..\\"), "C:\\" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\\\A\\\\B"), "C:\\A\\B" );
}
PYSTRING_ADD_TEST(pystring_os_path, split)
{
using namespace pystring::os::path;
std::string head, tail;
split_posix(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_posix(head, tail, "a/"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/a"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_posix(head, tail, "/a/b/"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/a/b"); PYSTRING_CHECK_EQUAL(head, "/a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
split_nt(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "\\"); PYSTRING_CHECK_EQUAL(head, "\\" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_nt(head, tail, "a\\"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "c:\\a"); PYSTRING_CHECK_EQUAL(head, "c:\\" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_nt(head, tail, "c:\\a\\b"); PYSTRING_CHECK_EQUAL(head, "c:\\a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
split_nt(head, tail, "c:\\a\\b\\"); PYSTRING_CHECK_EQUAL(head, "c:\\a\\b" ); PYSTRING_CHECK_EQUAL(tail, "" );
}
PYSTRING_ADD_TEST(pystring_os_path, splitext)
{
using namespace pystring::os::path;
std::string root, ext;
splitext_nt(root, ext, ""); PYSTRING_CHECK_EQUAL(root, ""); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, "."); PYSTRING_CHECK_EQUAL(root, "."); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, ".foo"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, ".foo."); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".");
splitext_nt(root, ext, ".foo.e"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".e");
splitext_nt(root, ext, "c"); PYSTRING_CHECK_EQUAL(root, "c"); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, "a_b.c"); PYSTRING_CHECK_EQUAL(root, "a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
splitext_nt(root, ext, "c:\\a.b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a.b"); PYSTRING_CHECK_EQUAL(ext, ".c");
splitext_nt(root, ext, "c:\\a_b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
}
#endif
+50 -2
View File
@@ -298,6 +298,23 @@ namespace os
{
namespace path
{
// All of the function below have three versions.
// Example:
// join(...)
// join_nt(...)
// join_posix(...)
//
// The regular function dispatches to the other versions - based on the OS
// at compile time - to match the result you'd get from the python
// interepreter on the same operating system
//
// Should you want to 'lock off' to a particular version of the string
// manipulation across *all* operating systems, use the version with the
// _OS you are interested in. I.e., you can use posix style path joining,
// even on Windows, with join_posix.
//
// The naming, (nt, posix) matches the cpython source implementation.
//////////////////////////////////////////////////////////////////////////////////////////////
/// @defgroup functions pystring::os::path
/// @{
@@ -309,12 +326,16 @@ namespace path
/// empty string ('').
std::string basename(const std::string & path);
std::string basename_nt(const std::string & path);
std::string basename_posix(const std::string & path);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return the directory name of pathname path. This is the first half of the pair
/// returned by split(path).
std::string dirname(const std::string & path);
std::string dirname_nt(const std::string & path);
std::string dirname_posix(const std::string & path);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return True if path is an absolute pathname. On Unix, that means it begins with a
@@ -322,6 +343,19 @@ namespace path
/// letter.
bool isabs(const std::string & path);
bool isabs_nt(const std::string & path);
bool isabs_posix(const std::string & s);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return a normalized absolutized version of the pathname path.
///
/// NOTE: This differs from the interface of the python equivalent in that it requires you
/// to pass in the current working directory as an argument.
std::string abspath(const std::string & path, const std::string & cwd);
std::string abspath_nt(const std::string & path, const std::string & cwd);
std::string abspath_posix(const std::string & path, const std::string & cwd);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Join one or more path components intelligently. If any component is an absolute
@@ -332,8 +366,14 @@ namespace path
/// directory for each drive, os.path.join("c:", "foo") represents a path relative to the
/// current directory on drive C: (c:foo), not c:\foo.
/// This dispatches based on the compilation OS
std::string join(const std::string & path1, const std::string & path2);
std::string join_nt(const std::string & path1, const std::string & path2);
std::string join_posix(const std::string & path1, const std::string & path2);
std::string join(const std::vector< std::string > & paths);
std::string join_nt(const std::vector< std::string > & paths);
std::string join_posix(const std::vector< std::string > & paths);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Normalize a pathname. This collapses redundant separators and up-level references
@@ -343,6 +383,8 @@ namespace path
/// symbolic links!
std::string normpath(const std::string & path);
std::string normpath_nt(const std::string & path);
std::string normpath_posix(const std::string & path);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
@@ -354,21 +396,27 @@ namespace path
/// differ).
void split(std::string & head, std::string & tail, const std::string & path);
void split_nt(std::string & head, std::string & tail, const std::string & path);
void split_posix(std::string & head, std::string & tail, const std::string & path);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
/// specification or the empty string. On systems which do not use drive specifications,
/// drive will always be the empty string. In all cases, drive + tail will be the same as
/// path.
void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Split the pathname path into a pair (root, ext) such that root + ext == path, and
/// ext is empty or begins with a period and contains at most one period. Leading periods on
/// the basename are ignored; splitext('.cshrc') returns ('.cshrc', '').
void splitext(std::string & root, std::string & ext, const std::string & path);
void splitext_nt(std::string & root, std::string & ext, const std::string & path);
void splitext_posix(std::string & root, std::string & ext, const std::string & path);
///
/// @ }
+492 -1
View File
@@ -5,7 +5,6 @@
PYSTRING_TEST_APP(PyStringUnitTests)
PYSTRING_ADD_TEST(pystring, endswith)
{
PYSTRING_CHECK_EQUAL(pystring::endswith("", ""), true);
@@ -95,6 +94,16 @@ PYSTRING_ADD_TEST(pystring, rfind)
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "abc", 6, 8), -1);
}
PYSTRING_ADD_TEST(pystring, replace)
{
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "foo", "bar"), "abcdef");
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "ab", "cd"), "cdcdef");
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "ab", ""), "cdef");
PYSTRING_CHECK_EQUAL(pystring::replace("abcabc", "ab", ""), "cc");
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "", ""), "abcdef");
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "", "."), ".a.b.c.d.e.f.");
}
PYSTRING_ADD_TEST(pystring, slice)
{
PYSTRING_CHECK_EQUAL(pystring::slice(""), "");
@@ -123,6 +132,343 @@ PYSTRING_ADD_TEST(pystring, slice)
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",0,-1), "abcde");
}
PYSTRING_ADD_TEST(pystring, split)
{
std::vector< std::string > result;
{
result.clear();
pystring::split("", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], "");
}
}
{
result.clear();
pystring::split("/", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::split(" ", result, " ", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::split(" /", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " ");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::split(" //", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " ");
PYSTRING_CHECK_EQUAL(result[1], "/");
}
}
{
result.clear();
pystring::split("a ", result, " ", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "a");
PYSTRING_CHECK_EQUAL(result[1], " ");
}
}
{
result.clear();
pystring::split("//as//rew//gdf", result, "//");
PYSTRING_CHECK_EQUAL(result.size(), 4);
if(result.size()==4)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "as");
PYSTRING_CHECK_EQUAL(result[2], "rew");
PYSTRING_CHECK_EQUAL(result[3], "gdf");
}
}
{
result.clear();
pystring::split("/root", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
}
}
{
result.clear();
pystring::split("/root/world", result, "/", 0);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], "/root/world");
}
}
{
result.clear();
pystring::split("/root/world", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root/world");
}
}
{
result.clear();
pystring::split("/root/world", result, "/", 2);
PYSTRING_CHECK_EQUAL(result.size(), 3);
if(result.size()==3)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
PYSTRING_CHECK_EQUAL(result[2], "world");
}
}
{
result.clear();
pystring::split("/root/world", result, "/", -1);
PYSTRING_CHECK_EQUAL(result.size(), 3);
if(result.size()==3)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
PYSTRING_CHECK_EQUAL(result[2], "world");
}
}
}
PYSTRING_ADD_TEST(pystring, rsplit)
{
std::vector< std::string > result;
{
result.clear();
pystring::rsplit("", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], "");
}
}
{
// "".rsplit(None, 1)
result.clear();
pystring::rsplit("", result, "", 1);
PYSTRING_CHECK_EQUAL(result.size(), 0);
}
{
// " ".rsplit(None, 1)
result.clear();
pystring::rsplit(" ", result, "", 1);
PYSTRING_CHECK_EQUAL(result.size(), 0);
}
{
result.clear();
pystring::rsplit(" ", result, "", 1);
PYSTRING_CHECK_EQUAL(result.size(), 0);
}
{
result.clear();
pystring::rsplit("/", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::rsplit(" /", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " ");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::rsplit(" //", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " /");
PYSTRING_CHECK_EQUAL(result[1], "");
}
}
{
result.clear();
pystring::rsplit("/root", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
}
}
{
result.clear();
pystring::rsplit("/root/world", result, "/", 0);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], "/root/world");
}
}
{
result.clear();
pystring::rsplit("/root/world", result, "/", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "/root");
PYSTRING_CHECK_EQUAL(result[1], "world");
}
}
{
result.clear();
pystring::rsplit("/root/world", result, "/", 2);
PYSTRING_CHECK_EQUAL(result.size(), 3);
if(result.size()==3)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
PYSTRING_CHECK_EQUAL(result[2], "world");
}
}
{
result.clear();
pystring::rsplit("/root/world", result, "/", -1);
PYSTRING_CHECK_EQUAL(result.size(), 3);
if(result.size()==3)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
PYSTRING_CHECK_EQUAL(result[2], "world");
}
}
{
// " root world".rsplit(None, 0)
result.clear();
pystring::rsplit(" root world", result, "", 0);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], " root world");
}
}
{
// " root world".rsplit(None, 1)
result.clear();
pystring::rsplit(" root world", result, "", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " root");
PYSTRING_CHECK_EQUAL(result[1], "world");
}
}
{
// " root world".rsplit(None, 2)
result.clear();
pystring::rsplit(" root world", result, "", 2);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], "root");
PYSTRING_CHECK_EQUAL(result[1], "world");
}
}
{
// " root world".rsplit(" ", 0)
result.clear();
pystring::rsplit(" root world", result, " ", 0);
PYSTRING_CHECK_EQUAL(result.size(), 1);
if(result.size()==1)
{
PYSTRING_CHECK_EQUAL(result[0], " root world");
}
}
{
// " root world".rsplit(" ", 1)
result.clear();
pystring::rsplit(" root world", result, " ", 1);
PYSTRING_CHECK_EQUAL(result.size(), 2);
if(result.size()==2)
{
PYSTRING_CHECK_EQUAL(result[0], " root");
PYSTRING_CHECK_EQUAL(result[1], "world");
}
}
{
// " root world".rsplit(" ", 2)
result.clear();
pystring::rsplit(" root world", result, " ", 2);
PYSTRING_CHECK_EQUAL(result.size(), 3);
if(result.size()==3)
{
PYSTRING_CHECK_EQUAL(result[0], "");
PYSTRING_CHECK_EQUAL(result[1], "root");
PYSTRING_CHECK_EQUAL(result[2], "world");
}
}
}
PYSTRING_ADD_TEST(pystring, startswith)
{
PYSTRING_CHECK_EQUAL(pystring::startswith("", ""), true);
@@ -163,3 +509,148 @@ PYSTRING_ADD_TEST(pystring, translate)
PYSTRING_CHECK_EQUAL(pystring::translate("", t2), "");
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t2), "chooso");
}
PYSTRING_ADD_TEST(pystring, abspath)
{
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("", "/net"), "/net");
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("../jeremys", "/net/soft_scratch/users/stevel"), "/net/soft_scratch/users/jeremys");
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("../../../../tmp/a", "/net/soft_scratch/users/stevel"), "/tmp/a");
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("", "c:\\net"), "c:\\net");
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("..\\jeremys", "c:\\net\\soft_scratch\\users\\stevel"), "c:\\net\\soft_scratch\\users\\jeremys");
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("..\\..\\..\\..\\tmp\\a", "c:\\net\\soft_scratch\\users\\stevel"), "c:\\tmp\\a");
}
PYSTRING_ADD_TEST(pystring_os_path, splitdrive)
{
using namespace pystring::os::path;
std::string drivespec, pathspec;
splitdrive_posix(drivespec, pathspec, "/Users/test"); PYSTRING_CHECK_EQUAL(drivespec, ""); PYSTRING_CHECK_EQUAL(pathspec, "/Users/test");
splitdrive_nt(drivespec, pathspec, "C:\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "C:" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
splitdrive_nt(drivespec, pathspec, "\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
}
PYSTRING_ADD_TEST(pystring_os_path, isabs)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(isabs_posix("/Users/test"), true );
PYSTRING_CHECK_EQUAL(isabs_posix("\\Users\\test"), false);
PYSTRING_CHECK_EQUAL(isabs_posix("../Users"), false);
PYSTRING_CHECK_EQUAL(isabs_posix("Users"), false);
PYSTRING_CHECK_EQUAL(isabs_nt("C:\\Users\\test"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("C:/Users"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("/Users"), true);
PYSTRING_CHECK_EQUAL(isabs_nt("../Users"), false);
PYSTRING_CHECK_EQUAL(isabs_nt("..\\Users"), false);
}
PYSTRING_ADD_TEST(pystring_os_path, join)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(join_posix("a","b"), "a/b" );
PYSTRING_CHECK_EQUAL(join_posix("/a","b"), "/a/b" );
PYSTRING_CHECK_EQUAL(join_posix("/a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("//a","b"), "//a/b" );
PYSTRING_CHECK_EQUAL(join_posix("//a","b//"), "//a/b//" );
PYSTRING_CHECK_EQUAL(join_posix("../a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_posix("../a","b"), "../a/b" );
std::vector< std::string > paths;
PYSTRING_CHECK_EQUAL(join_posix(paths), "" );
paths.push_back("/a");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a" );
paths.push_back("b");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b" );
paths.push_back("c/");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/" );
paths.push_back("d");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/d" );
paths.push_back("/e");
PYSTRING_CHECK_EQUAL(join_posix(paths), "/e" );
PYSTRING_CHECK_EQUAL(join_nt("c:","/a"), "c:/a" );
PYSTRING_CHECK_EQUAL(join_nt("c:/","/a"), "c:/a" );
PYSTRING_CHECK_EQUAL(join_nt("c:/a","/b"), "/b" );
PYSTRING_CHECK_EQUAL(join_nt("c:","d:/"), "d:/" );
PYSTRING_CHECK_EQUAL(join_nt("c:/","d:/"), "d:/" );
PYSTRING_CHECK_EQUAL(join_nt("a","b"), "a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("\\a","b"), "\\a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","b"), "c:\\a\\b" );
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","c:\\b"), "c:\\b" );
PYSTRING_CHECK_EQUAL(join_nt("..\\a","b"), "..\\a\\b" );
}
PYSTRING_ADD_TEST(pystring_os_path, normpath)
{
using namespace pystring::os::path;
PYSTRING_CHECK_EQUAL(normpath_posix("A//B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("A/./B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("A/foo/../B"), "A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("/A//B"), "/A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("//A//B"), "//A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("///A//B"), "/A/B" );
PYSTRING_CHECK_EQUAL(normpath_posix("../A"), "../A" );
PYSTRING_CHECK_EQUAL(normpath_posix("../A../"), "../A.." );
PYSTRING_CHECK_EQUAL(normpath_posix("FOO/../A../././B"), "A../B" );
PYSTRING_CHECK_EQUAL(normpath_nt(""), "." );
PYSTRING_CHECK_EQUAL(normpath_nt("A"), "A" );
PYSTRING_CHECK_EQUAL(normpath_nt("A./B"), "A.\\B" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\"), "C:\\" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\"), "C:\\A.." );
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\..\\"), "C:\\" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\A"), "C:\\A" );
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\\\A\\\\B"), "C:\\A\\B" );
}
PYSTRING_ADD_TEST(pystring_os_path, split)
{
using namespace pystring::os::path;
std::string head, tail;
split_posix(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_posix(head, tail, "a/"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/a"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_posix(head, tail, "/a/b/"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/a/b"); PYSTRING_CHECK_EQUAL(head, "/a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
split_posix(head, tail, "/a/b//"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_posix(head, tail, "/a/b/////////////"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "\\"); PYSTRING_CHECK_EQUAL(head, "\\" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_nt(head, tail, "a\\"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "c:\\a"); PYSTRING_CHECK_EQUAL(head, "c:\\" ); PYSTRING_CHECK_EQUAL(tail, "a" );
split_nt(head, tail, "c:\\a\\b"); PYSTRING_CHECK_EQUAL(head, "c:\\a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
split_nt(head, tail, "c:\\a\\b\\"); PYSTRING_CHECK_EQUAL(head, "c:\\a\\b" ); PYSTRING_CHECK_EQUAL(tail, "" );
split_nt(head, tail, "D:\\dir\\\\"); PYSTRING_CHECK_EQUAL(head, "D:\\dir" ); PYSTRING_CHECK_EQUAL(tail, "" );
}
PYSTRING_ADD_TEST(pystring_os_path, splitext)
{
using namespace pystring::os::path;
std::string root, ext;
splitext_nt(root, ext, ""); PYSTRING_CHECK_EQUAL(root, ""); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, "."); PYSTRING_CHECK_EQUAL(root, "."); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, ".foo"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, ".foo."); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".");
splitext_nt(root, ext, ".foo.e"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".e");
splitext_nt(root, ext, "c"); PYSTRING_CHECK_EQUAL(root, "c"); PYSTRING_CHECK_EQUAL(ext, "");
splitext_nt(root, ext, "a_b.c"); PYSTRING_CHECK_EQUAL(root, "a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
splitext_nt(root, ext, "c:\\a.b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a.b"); PYSTRING_CHECK_EQUAL(ext, ".c");
splitext_nt(root, ext, "c:\\a_b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
}