Skip to content

Commit ae50dda

Browse files
committed
exposed all os::path posix vs. nt varients
1 parent a5c3cfa commit ae50dda

File tree

3 files changed

+226
-144
lines changed

3 files changed

+226
-144
lines changed

pystring.cpp

Lines changed: 55 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,13 +1131,29 @@ namespace path
11311131
//////////////////////////////////////////////////////////////////////////////////////////////
11321132
///
11331133
///
1134-
std::string abspath(const std::string & path, const std::string & cwd)
1134+
1135+
std::string abspath_nt(const std::string & path, const std::string & cwd)
1136+
{
1137+
std::string p = path;
1138+
if(!isabs_nt(p)) p = join_nt(cwd, p);
1139+
return normpath_nt(p);
1140+
}
1141+
1142+
std::string abspath_posix(const std::string & path, const std::string & cwd)
11351143
{
11361144
std::string p = path;
1137-
if(!isabs(p)) p = join(cwd, p);
1138-
return normpath(p);
1145+
if(!isabs_posix(p)) p = join_posix(cwd, p);
1146+
return normpath_posix(p);
11391147
}
11401148

1149+
std::string abspath(const std::string & path, const std::string & cwd)
1150+
{
1151+
#ifdef WINDOWS
1152+
return abspath_nt(path, cwd);
1153+
#else
1154+
return abspath_posix(path, cwd);
1155+
#endif
1156+
}
11411157

11421158

11431159
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -1372,19 +1388,51 @@ namespace path
13721388
///
13731389
///
13741390

1375-
std::string basename(const std::string & path)
1391+
std::string basename_nt(const std::string & path)
13761392
{
13771393
std::string head, tail;
1378-
split(head, tail, path);
1394+
split_nt(head, tail, path);
13791395
return tail;
13801396
}
13811397

1382-
std::string dirname(const std::string & path)
1398+
std::string basename_posix(const std::string & path)
1399+
{
1400+
std::string head, tail;
1401+
split_posix(head, tail, path);
1402+
return tail;
1403+
}
1404+
1405+
std::string basename(const std::string & path)
1406+
{
1407+
#ifdef WINDOWS
1408+
return basename_nt(path);
1409+
#else
1410+
return basename_posix(path);
1411+
#endif
1412+
}
1413+
1414+
std::string dirname_nt(const std::string & path)
1415+
{
1416+
std::string head, tail;
1417+
split_nt(head, tail, path);
1418+
return head;
1419+
}
1420+
1421+
std::string dirname_posix(const std::string & path)
13831422
{
13841423
std::string head, tail;
1385-
split(head, tail, path);
1424+
split_posix(head, tail, path);
13861425
return head;
13871426
}
1427+
1428+
std::string dirname(const std::string & path)
1429+
{
1430+
#ifdef WINDOWS
1431+
return dirname_nt(path);
1432+
#else
1433+
return dirname_posix(path);
1434+
#endif
1435+
}
13881436

13891437

13901438
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -1602,138 +1650,3 @@ namespace path
16021650
}//namespace pystring
16031651

16041652

1605-
#ifdef PYSTRING_UNITTEST
1606-
1607-
#include "unittest.h"
1608-
1609-
PYSTRING_ADD_TEST(pystring_os_path, splitdrive)
1610-
{
1611-
using namespace pystring::os::path;
1612-
1613-
std::string drivespec, pathspec;
1614-
splitdrive_posix(drivespec, pathspec, "/Users/test"); PYSTRING_CHECK_EQUAL(drivespec, ""); PYSTRING_CHECK_EQUAL(pathspec, "/Users/test");
1615-
splitdrive_nt(drivespec, pathspec, "C:\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "C:" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
1616-
splitdrive_nt(drivespec, pathspec, "\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
1617-
}
1618-
1619-
PYSTRING_ADD_TEST(pystring_os_path, isabs)
1620-
{
1621-
using namespace pystring::os::path;
1622-
1623-
PYSTRING_CHECK_EQUAL(isabs_posix("/Users/test"), true );
1624-
PYSTRING_CHECK_EQUAL(isabs_posix("\\Users\\test"), false);
1625-
PYSTRING_CHECK_EQUAL(isabs_posix("../Users"), false);
1626-
PYSTRING_CHECK_EQUAL(isabs_posix("Users"), false);
1627-
1628-
PYSTRING_CHECK_EQUAL(isabs_nt("C:\\Users\\test"), true);
1629-
PYSTRING_CHECK_EQUAL(isabs_nt("C:/Users"), true);
1630-
PYSTRING_CHECK_EQUAL(isabs_nt("/Users"), true);
1631-
PYSTRING_CHECK_EQUAL(isabs_nt("../Users"), false);
1632-
PYSTRING_CHECK_EQUAL(isabs_nt("..\\Users"), false);
1633-
}
1634-
1635-
PYSTRING_ADD_TEST(pystring_os_path, join)
1636-
{
1637-
using namespace pystring::os::path;
1638-
1639-
PYSTRING_CHECK_EQUAL(join_posix("a","b"), "a/b" );
1640-
PYSTRING_CHECK_EQUAL(join_posix("/a","b"), "/a/b" );
1641-
PYSTRING_CHECK_EQUAL(join_posix("/a","/b"), "/b" );
1642-
PYSTRING_CHECK_EQUAL(join_posix("a","/b"), "/b" );
1643-
PYSTRING_CHECK_EQUAL(join_posix("//a","b"), "//a/b" );
1644-
PYSTRING_CHECK_EQUAL(join_posix("//a","b//"), "//a/b//" );
1645-
PYSTRING_CHECK_EQUAL(join_posix("../a","/b"), "/b" );
1646-
PYSTRING_CHECK_EQUAL(join_posix("../a","b"), "../a/b" );
1647-
1648-
std::vector< std::string > paths;
1649-
PYSTRING_CHECK_EQUAL(join_posix(paths), "" );
1650-
paths.push_back("/a");
1651-
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a" );
1652-
paths.push_back("b");
1653-
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b" );
1654-
paths.push_back("c/");
1655-
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/" );
1656-
paths.push_back("d");
1657-
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/d" );
1658-
paths.push_back("/e");
1659-
PYSTRING_CHECK_EQUAL(join_posix(paths), "/e" );
1660-
1661-
PYSTRING_CHECK_EQUAL(join_nt("c:","/a"), "c:/a" );
1662-
PYSTRING_CHECK_EQUAL(join_nt("c:/","/a"), "c:/a" );
1663-
PYSTRING_CHECK_EQUAL(join_nt("c:/a","/b"), "/b" );
1664-
PYSTRING_CHECK_EQUAL(join_nt("c:","d:/"), "d:/" );
1665-
PYSTRING_CHECK_EQUAL(join_nt("c:/","d:/"), "d:/" );
1666-
PYSTRING_CHECK_EQUAL(join_nt("a","b"), "a\\b" );
1667-
PYSTRING_CHECK_EQUAL(join_nt("\\a","b"), "\\a\\b" );
1668-
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","b"), "c:\\a\\b" );
1669-
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","c:\\b"), "c:\\b" );
1670-
PYSTRING_CHECK_EQUAL(join_nt("..\\a","b"), "..\\a\\b" );
1671-
}
1672-
1673-
PYSTRING_ADD_TEST(pystring_os_path, normpath)
1674-
{
1675-
using namespace pystring::os::path;
1676-
1677-
PYSTRING_CHECK_EQUAL(normpath_posix("A//B"), "A/B" );
1678-
PYSTRING_CHECK_EQUAL(normpath_posix("A/./B"), "A/B" );
1679-
PYSTRING_CHECK_EQUAL(normpath_posix("A/foo/../B"), "A/B" );
1680-
PYSTRING_CHECK_EQUAL(normpath_posix("/A//B"), "/A/B" );
1681-
PYSTRING_CHECK_EQUAL(normpath_posix("//A//B"), "//A/B" );
1682-
PYSTRING_CHECK_EQUAL(normpath_posix("///A//B"), "/A/B" );
1683-
PYSTRING_CHECK_EQUAL(normpath_posix("../A"), "../A" );
1684-
PYSTRING_CHECK_EQUAL(normpath_posix("../A../"), "../A.." );
1685-
PYSTRING_CHECK_EQUAL(normpath_posix("FOO/../A../././B"), "A../B" );
1686-
1687-
PYSTRING_CHECK_EQUAL(normpath_nt(""), "." );
1688-
PYSTRING_CHECK_EQUAL(normpath_nt("A"), "A" );
1689-
PYSTRING_CHECK_EQUAL(normpath_nt("A./B"), "A.\\B" );
1690-
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\"), "C:\\" );
1691-
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\A"), "C:\\A" );
1692-
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A"), "C:\\A" );
1693-
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\"), "C:\\A.." );
1694-
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\..\\"), "C:\\" );
1695-
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\A"), "C:\\A" );
1696-
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\\\A\\\\B"), "C:\\A\\B" );
1697-
}
1698-
1699-
PYSTRING_ADD_TEST(pystring_os_path, split)
1700-
{
1701-
using namespace pystring::os::path;
1702-
1703-
std::string head, tail;
1704-
split_posix(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
1705-
split_posix(head, tail, "/"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "" );
1706-
split_posix(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
1707-
split_posix(head, tail, "a/"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
1708-
split_posix(head, tail, "/a"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "a" );
1709-
split_posix(head, tail, "/a/b/"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
1710-
split_posix(head, tail, "/a/b"); PYSTRING_CHECK_EQUAL(head, "/a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
1711-
1712-
split_nt(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
1713-
split_nt(head, tail, "\\"); PYSTRING_CHECK_EQUAL(head, "\\" ); PYSTRING_CHECK_EQUAL(tail, "" );
1714-
split_nt(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
1715-
split_nt(head, tail, "a\\"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
1716-
split_nt(head, tail, "c:\\a"); PYSTRING_CHECK_EQUAL(head, "c:\\" ); PYSTRING_CHECK_EQUAL(tail, "a" );
1717-
split_nt(head, tail, "c:\\a\\b"); PYSTRING_CHECK_EQUAL(head, "c:\\a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
1718-
split_nt(head, tail, "c:\\a\\b\\"); PYSTRING_CHECK_EQUAL(head, "c:\\a\\b" ); PYSTRING_CHECK_EQUAL(tail, "" );
1719-
}
1720-
1721-
PYSTRING_ADD_TEST(pystring_os_path, splitext)
1722-
{
1723-
using namespace pystring::os::path;
1724-
1725-
std::string root, ext;
1726-
splitext_nt(root, ext, ""); PYSTRING_CHECK_EQUAL(root, ""); PYSTRING_CHECK_EQUAL(ext, "");
1727-
splitext_nt(root, ext, "."); PYSTRING_CHECK_EQUAL(root, "."); PYSTRING_CHECK_EQUAL(ext, "");
1728-
splitext_nt(root, ext, ".foo"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, "");
1729-
splitext_nt(root, ext, ".foo."); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".");
1730-
splitext_nt(root, ext, ".foo.e"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".e");
1731-
splitext_nt(root, ext, "c"); PYSTRING_CHECK_EQUAL(root, "c"); PYSTRING_CHECK_EQUAL(ext, "");
1732-
splitext_nt(root, ext, "a_b.c"); PYSTRING_CHECK_EQUAL(root, "a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
1733-
splitext_nt(root, ext, "c:\\a.b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a.b"); PYSTRING_CHECK_EQUAL(ext, ".c");
1734-
splitext_nt(root, ext, "c:\\a_b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
1735-
}
1736-
1737-
#endif
1738-
1739-

pystring.h

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,23 @@ namespace os
298298
{
299299
namespace path
300300
{
301+
// All of the function below have three versions.
302+
// Example:
303+
// join(...)
304+
// join_nt(...)
305+
// join_posix(...)
306+
//
307+
// The regular function dispatches to the other versions - based on the OS
308+
// at compile time - to match the result you'd get from the python
309+
// interepreter on the same operating system
310+
//
311+
// Should you want to 'lock off' to a particular version of the string
312+
// manipulation across *all* operating systems, use the version with the
313+
// _OS you are interested in. I.e., you can use posix style path joining,
314+
// even on Windows, with join_posix.
315+
//
316+
// The naming, (nt, posix) matches the cpython source implementation.
317+
301318
//////////////////////////////////////////////////////////////////////////////////////////////
302319
/// @defgroup functions pystring::os::path
303320
/// @{
@@ -309,26 +326,35 @@ namespace path
309326
/// empty string ('').
310327

311328
std::string basename(const std::string & path);
329+
std::string basename_nt(const std::string & path);
330+
std::string basename_posix(const std::string & path);
312331

313332
//////////////////////////////////////////////////////////////////////////////////////////////
314333
/// @brief Return the directory name of pathname path. This is the first half of the pair
315334
/// returned by split(path).
316335

317336
std::string dirname(const std::string & path);
337+
std::string dirname_nt(const std::string & path);
338+
std::string dirname_posix(const std::string & path);
318339

319340
//////////////////////////////////////////////////////////////////////////////////////////////
320341
/// @brief Return True if path is an absolute pathname. On Unix, that means it begins with a
321342
/// slash, on Windows that it begins with a (back)slash after chopping off a potential drive
322343
/// letter.
323344

324345
bool isabs(const std::string & path);
346+
bool isabs_nt(const std::string & path);
347+
bool isabs_posix(const std::string & s);
325348

326349
//////////////////////////////////////////////////////////////////////////////////////////////
327350
/// @brief Return a normalized absolutized version of the pathname path.
328351
///
329352
/// NOTE: This differs from the interface of the python equivalent in that it requires you
330353
/// to pass in the current working directory as an argument.
354+
331355
std::string abspath(const std::string & path, const std::string & cwd);
356+
std::string abspath_nt(const std::string & path, const std::string & cwd);
357+
std::string abspath_posix(const std::string & path, const std::string & cwd);
332358

333359

334360
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -340,8 +366,14 @@ namespace path
340366
/// directory for each drive, os.path.join("c:", "foo") represents a path relative to the
341367
/// current directory on drive C: (c:foo), not c:\foo.
342368

369+
/// This dispatches based on the compilation OS
343370
std::string join(const std::string & path1, const std::string & path2);
371+
std::string join_nt(const std::string & path1, const std::string & path2);
372+
std::string join_posix(const std::string & path1, const std::string & path2);
373+
344374
std::string join(const std::vector< std::string > & paths);
375+
std::string join_nt(const std::vector< std::string > & paths);
376+
std::string join_posix(const std::vector< std::string > & paths);
345377

346378
//////////////////////////////////////////////////////////////////////////////////////////////
347379
/// @brief Normalize a pathname. This collapses redundant separators and up-level references
@@ -351,6 +383,8 @@ namespace path
351383
/// symbolic links!
352384

353385
std::string normpath(const std::string & path);
386+
std::string normpath_nt(const std::string & path);
387+
std::string normpath_posix(const std::string & path);
354388

355389
//////////////////////////////////////////////////////////////////////////////////////////////
356390
/// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
@@ -362,21 +396,27 @@ namespace path
362396
/// differ).
363397

364398
void split(std::string & head, std::string & tail, const std::string & path);
399+
void split_nt(std::string & head, std::string & tail, const std::string & path);
400+
void split_posix(std::string & head, std::string & tail, const std::string & path);
365401

366402
//////////////////////////////////////////////////////////////////////////////////////////////
367403
/// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
368404
/// specification or the empty string. On systems which do not use drive specifications,
369405
/// drive will always be the empty string. In all cases, drive + tail will be the same as
370406
/// path.
371-
407+
372408
void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
373-
409+
void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
410+
void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
411+
374412
//////////////////////////////////////////////////////////////////////////////////////////////
375413
/// @brief Split the pathname path into a pair (root, ext) such that root + ext == path, and
376414
/// ext is empty or begins with a period and contains at most one period. Leading periods on
377415
/// the basename are ignored; splitext('.cshrc') returns ('.cshrc', '').
378416

379417
void splitext(std::string & root, std::string & ext, const std::string & path);
418+
void splitext_nt(std::string & root, std::string & ext, const std::string & path);
419+
void splitext_posix(std::string & root, std::string & ext, const std::string & path);
380420

381421
///
382422
/// @ }

0 commit comments

Comments
 (0)