2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 01:12:13 +00:00

Port Jambase to C++.

This ports the minimal Jambase to native C++. This removes the need for
mkjambase and the Jambase files. To accomplish that it adds C++
utility wrapers around Jam language primitives. Which makes future
similar work much easier.
This commit is contained in:
Rene Rivera
2020-06-22 08:48:24 -05:00
parent 269272327e
commit 59b7a6dc69
24 changed files with 1119 additions and 1218 deletions

View File

@@ -35,6 +35,8 @@
#include <stdlib.h>
#include <time.h>
#include <algorithm>
/* Internal OS specific implementation details - have names ending with an
* underscore and are expected to be implemented in an OS specific pathXXX.c
@@ -300,3 +302,65 @@ int path_translate_to_os( char const * f, string * file )
{
return path_translate_to_os_( f, file );
}
std::string b2::paths::normalize(const std::string &p)
{
// We root the path as a sentinel. But we need to remember that we did so
// to un-root afterwards.
std::string result{"/"};
bool is_rooted = p[0] == '/' || p[0] == '\\';
result += p;
// Convert \ into /. On Windows, paths using / and \ are equivalent, and we
// want this function to obtain a canonic representation.
std::replace(result.begin(), result.end(), '\\', '/');
size_t ellipsis = 0;
for (auto end_pos = result.length(); end_pos > 0; )
{
auto path_pos = result.rfind('/', end_pos-1);
if (path_pos == std::string::npos) break;
if (path_pos == end_pos-1)
{
/* Found a trailing or duplicate '/'. Remove it. */
result.erase(path_pos, 1);
}
else if ((end_pos-path_pos == 2) && result[path_pos+1] == '.')
{
/* Found '/.'. Remove them all. */
result.erase(path_pos, 2);
}
else if ((end_pos-path_pos == 3) && result[path_pos+1] == '.' && result[path_pos+2] == '.')
{
/* Found '/..'. Remove them all. */
result.erase(path_pos, 3);
ellipsis += 1;
}
else if (ellipsis > 0)
{
/* An elided parent path. Remove it. */
result.erase(path_pos, end_pos-path_pos);
ellipsis -= 1;
}
end_pos = path_pos;
}
// Now we know that we need to add exactly ellipsis '..' path elements to the
// front and that our string is either empty or has a '/' as its first
// significant character. If we have any ellipsis remaining then the passed
// path must not have been rooted or else it is invalid we return empty.
if (ellipsis > 0)
{
if (is_rooted) return "";
do result.insert(0, "/.."); while (--ellipsis > 0);
}
// If we reduced to nothing we return a valid path depending on wether
// the input was rooted or not.
if (result.empty()) return is_rooted ? "/" : ".";
// Return the result without the sentinel if it's not rooted.
if (!is_rooted) return result.substr(1);
return result;
}