flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

155
tjp/core/url/URL.cpp Executable file
View File

@@ -0,0 +1,155 @@
// TJP COPYRIGHT HEADER
#include "URL.h"
#include <tjp/core/string/str_find.h>
#include <tjp/core/algorithm/is_in.hpp>
#include <tjp/core/iterators/range.hpp>
#include <tjp/core/assert/debug_assert.h>
#include <tjp/core/algorithm/unused.hpp>
namespace tjp::core::url {
const char S = '/';
const char D = '#';
const char P = ':';
URL make(const Domain &domain)
{
debug_assert(domain.find(D)==-1);
debug_assert(domain.find(S)==-1);
return domain + D;
}
IP getIP(const URL &url)
{
auto p = url.find(P);
if (p == -1)
return {};
return url.substr(0,p);
}
Address getAddress(const URL &url)
{
auto d = url.find(D);
if (d == -1)
return {};
return url.substr(0,d);
}
Domain getDomain(const URL &url)
{
auto d = url.find(D);
return url.substr(0,d+1);
}
Path getPath(const URL &url)
{
return url.substr(url.find(D) + 1);
}
URL push_back(const URL &lhs, const URL &rhs)
{
debug_assert(rhs.find(D)==-1);
if (rhs.empty())
return lhs;
auto domain = getDomain(lhs);
auto path0 = getPath(lhs);
auto path1 = getPath(rhs);
auto s0 = path0.empty() ? "" : (path1.empty() ? "" : "/");
return domain + path0 + s0 + path1;
}
URL pop_back_(const URL &url)
{
int i;
for (i=(int)url.size()-1; i>0; --i)
if (is_in(url[i], D, S))
break;
if (i < 0)
return {};
if (url[i] == D)
return url.substr(0,i+1);
return url.substr(0,i);
}
URL pop_front_(const URL &url)
{
int i;
for (i=0; i<url.size(); ++i)
if (is_in(url[i], D, S))
break;
if (i >= url.size())
return {};
return url.substr(i+1);
}
URL pop_back(const URL &url_, size_t num)
{
auto url = url_;
for (auto i : range(num))
{
unused(i);
url = pop_back_(url);
}
return url;
}
URL pop_front(const URL &url_, size_t num)
{
auto url = url_;
for (auto i : range(num))
{
unused(i);
url = pop_front_(url);
}
return url;
}
URL back(const URL &url)
{
int i;
for (i=(int)url.size()-1; i>=0; --i)
{
if (is_in(url[i], D, S))
break;
}
return url.substr(i+1);
}
URL front(const URL &url)
{
auto path = getPath(url);
int i;
for (i=0; i<path.size(); ++i)
if (is_in(path[i], D, S))
break;
return url.substr(0, i);
}
bool hasPath(const URL &url)
{
return !getPath(url).empty();
}
} // namespace

53
tjp/core/url/URL.h Executable file
View File

@@ -0,0 +1,53 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <string>
namespace tjp {
namespace core {
namespace url {
using URL = std::string;
using Domain = std::string;
using Path = std::string;
using Part = std::string;
using Address = std::string;
using IP = std::string;
URL make(const Domain &domain);
template<typename ...Args>
URL make(const Domain &domain, Args&& ...args);
IP getIP(const URL &url);
Address getAddress(const URL &url);
Domain getDomain(const URL &url);
Path getPath(const URL &url);
URL pop_front(const URL &, size_t num=1);
URL pop_back(const URL &url, size_t num=1);
URL push_front(const URL &lhs, const URL &rhs);
URL push_back(const URL &url, const URL &rhs);
template<typename ...Args>
URL push_back(const URL &url, const URL &rhs, Args&& ...args);
template<typename ...Args>
URL push_front(const URL &url, const URL &rhs, Args&& ...args);
URL back(const URL &url);
URL front(const URL &url);
bool hasPath(const URL &url);
} // namespace
using URL = url::URL;
} // namespace
} // namespace
#include "URL.inl"

32
tjp/core/url/URL.inl Executable file
View File

@@ -0,0 +1,32 @@
// TJP COPYRIGHT HEADER
#pragma once
#include "URL.h"
namespace tjp {
namespace core {
namespace url {
template<typename ...Args>
URL make(const Domain &domain, Args&& ...args)
{
return push_back(
make(domain),
std::forward<Args>(args)...
);
}
template<typename ...Args>
URL push_back(const URL &url, const URL &rhs, Args&& ...args)
{
return push_back(
push_back(url, rhs),
std::forward<Args>(args)...
);
}
} // namespace
} // namespace
} // namespace

110
tjp/core/url/_tests/URL.cpp Executable file
View File

@@ -0,0 +1,110 @@
// TJP COPYRIGHT HEADER
#include <tjp/core/url/URL.h>
#include <tjp/core/testing/catch.hpp>
namespace tjp {
namespace core {
namespace url {
SCENARIO("url tests" )
{
GIVEN("url with just a domain")
{
Address address = "address";
Path empty;
URL domain = url::make(address);
auto url0 = domain;
REQUIRE(getAddress(url0) == address);
REQUIRE(getDomain(url0) == domain);
WHEN("adding a path")
{
Path path1 = "path1";
URL url1 = push_back(url0, path1);
REQUIRE(getPath(url1) == path1);
REQUIRE(getDomain(url1) == domain);
REQUIRE(getAddress(url1) == address);
Path path2 = "path2";
URL url2 = push_back(url1, path2);
REQUIRE(getPath(url2) == push_back(path1, path2));
REQUIRE(getDomain(url2) == domain);
REQUIRE(getAddress(url2) == address);
}
WHEN("back a path")
{
auto path = back(url0);
REQUIRE(path == empty);
}
}
GIVEN("url")
{
Address address = "address";
URL domain = make(address);
Path path1 = "path1";
auto url0 = domain;
URL url1 = make(address, path1);
REQUIRE(getDomain(domain) == domain);
REQUIRE(getPath(url1) == path1);
WHEN("adding a path")
{
Path path2 = "path2";
URL url2 = push_back(url1, path2);
REQUIRE(getPath(url2) == push_back(path1, path2));
REQUIRE(getDomain(url2) == domain);
REQUIRE(getAddress(url2) == address);
Path path3 = "path3";
URL url3 = push_back(url2, path3);
REQUIRE(getPath(url3) == push_back(path1, push_back(path2, path3)));
REQUIRE(getDomain(url3) == domain);
REQUIRE(getAddress(url3) == address);
}
WHEN("back a path")
{
auto path1_ = back(url1);
REQUIRE(path1_ == path1);
}
}
GIVEN("url")
{
Address address = "address";
Domain domain = make(address);
Path path1 = "path1";
Path path2 = "path2";
auto url0 = domain;
auto url2 = push_back(push_back(url0, path1), path2);
REQUIRE(getDomain(url2) == domain);
REQUIRE(getPath(url2) == push_back
(path1, path2));
WHEN("popping a path")
{
auto url1 = pop_back(url2);
REQUIRE(url1 == make(address, path1));
auto url0 = pop_back(url1);
REQUIRE(url0 == make(address));
}
WHEN("back a path")
{
auto path2_ = back(url2);
REQUIRE(path2 == path2_);
}
}
}
} // namespace
} // namespace
} // namespace