Skip to content

Commit 83f468c

Browse files
committed
#208-implement slices
Completed. Compiles. Still to be tested.
1 parent 042fcca commit 83f468c

File tree

1 file changed

+267
-4
lines changed

1 file changed

+267
-4
lines changed

cpp-strings/cppstrings.h

Lines changed: 267 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <cctype>
2828
#include <cwctype>
2929
#include <format>
30+
#include <limits>
3031
#include <map>
3132
#include <ranges>
3233
#include <span>
@@ -52,6 +53,37 @@ namespace pcs // i.e. "pythonic c++ strings"
5253
using CppString = CppStringT<char>; //!< Specialization of basic class with template argument 'char'
5354
using CppWString = CppStringT<wchar_t>; //!< Specialization of basic class with template argument 'wchar_t'
5455

56+
57+
// slices -- to be used with operator CppStringT::operator().
58+
template<typename IntT = std::int64_t>
59+
requires std::is_signed_v<IntT>
60+
class Slice; //!< Base class for slices, with start, stop and step specified values
61+
62+
template<typename IntT = std::int64_t>
63+
requires std::is_signed_v<IntT>
64+
struct StartSlice; //!< struct of slices with default stop and step values
65+
66+
template<typename IntT = std::int64_t>
67+
requires std::is_signed_v<IntT>
68+
struct StopSlice; //!< struct of slices with default start and step values
69+
70+
template<typename IntT = std::int64_t>
71+
requires std::is_signed_v<IntT>
72+
struct StepSlice; //!< struct of slices with default start and stop values
73+
74+
template<typename IntT = std::int64_t>
75+
requires std::is_signed_v<IntT>
76+
struct StartStopSlice; //!< struct of slices with default step values
77+
78+
template<typename IntT = std::int64_t>
79+
requires std::is_signed_v<IntT>
80+
struct StartStepSlice; //!< struct of slices with default stop values
81+
82+
template<typename IntT = std::int64_t>
83+
requires std::is_signed_v<IntT>
84+
struct StopStepSlice; //!< struct of slices with default start values
85+
86+
5587
// litteral operators
5688
#pragma warning(disable: 4455)
5789
inline CppString operator""cs(const char* str, std::size_t len); //!< Forms a CppString literal.
@@ -126,12 +158,12 @@ namespace pcs // i.e. "pythonic c++ strings"
126158
* - char32_t (C++11)
127159
*/
128160
template<class CharT, class TraitsT, class AllocatorT>
129-
class CppStringT : public std::basic_string<CharT>
161+
class CppStringT : public std::basic_string<CharT, TraitsT, AllocatorT>
130162
{
131163
public:
132164
//=== Wrappers ========================================
133-
using MyBaseClass = std::basic_string<CharT>;
134-
using MyStringView = std::basic_string_view<CharT>;
165+
using MyBaseClass = std::basic_string<CharT, TraitsT, AllocatorT>;
166+
using MyStringView = std::basic_string_view<CharT, TraitsT>;
135167

136168
using traits_type = MyBaseClass::traits_type;
137169
using value_type = MyBaseClass::value_type;
@@ -1030,8 +1062,75 @@ namespace pcs // i.e. "pythonic c++ strings"
10301062
}
10311063

10321064

1065+
//--- operator () -------------------------------------
1066+
/** \brief Generates a new string according to the specified slice.
1067+
*
1068+
* A slice is a range specified as [start, stop, step]. It may
1069+
* also be specified as [start, stop] in which case step = 1,
1070+
* or as [stop] in wich case start = 0 and step = 1.
1071+
* Values may be negative: negative step means reverse running
1072+
* and negative start or stop is relative to the end of the
1073+
* string.
1074+
* Notice: the stop value specifies an out of bounds index.
1075+
*/
1076+
inline CppStringT operator() (const long stop) const noexcept
1077+
{
1078+
size_type end{ stop < 0 ? this->size() + stop : stop };
1079+
return this->substr(0, end);
1080+
}
1081+
1082+
/** \brief Generates a new string according to the specified slice. */
1083+
inline CppStringT operator() (const long start, const long stop) const noexcept
1084+
{
1085+
const size_type length{ this->size() };
1086+
size_type begin{ start < 0 ? length + start : start };
1087+
size_type end{ stop < 0 ? length + stop : stop };
1088+
1089+
if (begin >= end)
1090+
return CppStringT();
1091+
else
1092+
return this->substr(begin, end - begin);
1093+
}
1094+
1095+
/** \brief Generates a new string according to the specified slice. */
1096+
CppStringT operator() (const long start, const long stop, const long step) const noexcept
1097+
{
1098+
CppStringT res{};
1099+
1100+
const size_type length{ this->size() };
1101+
size_type begin{ start < 0 ? length + start : start };
1102+
size_type end{ stop < 0 ? length + stop : stop };
1103+
1104+
if (step < 0) {
1105+
if (begin >= length)
1106+
begin = length - 1;
1107+
if (end < 0)
1108+
end = -1;
1109+
1110+
if (begin > end) {
1111+
for (size_type i = begin; i > end; i += step)
1112+
res += (*this)[i];
1113+
}
1114+
}
1115+
else if (step > 0) {
1116+
if (begin < 0)
1117+
begin = 0;
1118+
if (end > length)
1119+
end = length;
1120+
1121+
if (begin < end) {
1122+
for (size_type i = begin; i < end; i += step)
1123+
res += (*this)[i];
1124+
}
1125+
}
1126+
1127+
return res;
1128+
}
1129+
1130+
1131+
10331132
//--- operator * --------------------------------------
1034-
/** Generates a new string with count times the content of this string. */
1133+
/** \brief Generates a new string with count times the content of this string. */
10351134
CppStringT operator* (std::int64_t count) const noexcept
10361135
{
10371136
if (count <= 0)
@@ -1736,6 +1835,170 @@ namespace pcs // i.e. "pythonic c++ strings"
17361835
};
17371836

17381837

1838+
//===== Slices ========================================
1839+
//--- slices base -------------------------------------
1840+
/** \brief Base class for slices, with start, stop and step specified values. */
1841+
template<typename IntT>
1842+
requires std::is_signed_v<IntT>
1843+
class Slice
1844+
{
1845+
public:
1846+
static constexpr IntT DEFAULT{ std::numeric_limits<IntT>::min()};
1847+
1848+
//--- Constructors / Destructor -------------------
1849+
Slice() noexcept = default; //!< Default constructor
1850+
1851+
Slice(const IntT start, const IntT stop, const IntT step) noexcept //!< Valued constructor
1852+
: _start(start)
1853+
, _stop(stop)
1854+
, _step(step)
1855+
{}
1856+
1857+
virtual ~Slice() noexcept = default; //!< Default destructor.
1858+
1859+
1860+
//--- iterating -----------------------------------
1861+
inline const IntT begin(const CppString& str) noexcept //!< starts iterating on specified CppString.
1862+
{
1863+
if (_start == DEFAULT)
1864+
_start = 0;
1865+
else if (_start < 0)
1866+
_start += str.size();
1867+
1868+
if (_stop == DEFAULT)
1869+
_stop = str.size();
1870+
else if (_stop < 0)
1871+
_stop += str.size();
1872+
1873+
if (_step == DEFAULT)
1874+
_step = 1;
1875+
1876+
return _index = _start;
1877+
}
1878+
1879+
inline const bool end() const noexcept //!< returns true when iterating is over, or false otherwise.
1880+
{
1881+
return _step == 0 ? true : _step > 0 ? _index >= _stop : _index <= _stop;
1882+
}
1883+
1884+
inline const IntT operator++() noexcept //!< iterates one step, pre-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value.
1885+
{
1886+
return _index += _step;
1887+
}
1888+
1889+
inline const IntT operator++(int) noexcept //!< iterates one step, post-increment. Caution: returned index may be out of bounds. Check '!end()' before using its value.
1890+
{
1891+
_index += _step;
1892+
return _index - _step;
1893+
}
1894+
1895+
1896+
private:
1897+
IntT _start{ 0 };
1898+
IntT _stop{ DEFAULT };
1899+
IntT _step{ 1 };
1900+
1901+
IntT _index{ 0 };
1902+
};
1903+
1904+
1905+
/** \brief Class of slices with default stop and step values. */
1906+
template<typename IntT>
1907+
requires std::is_signed_v<IntT>
1908+
struct StartSlice : public Slice<IntT>
1909+
{
1910+
//--- Constructors / Destructor -------------------
1911+
StartSlice() noexcept = default; //!< Default constructor
1912+
1913+
inline StartSlice(const IntT start) noexcept //!< Valued constructor
1914+
: Slice(start, Slice::DEFAULT, 1)
1915+
{}
1916+
1917+
virtual ~StartSlice() noexcept = default; //!< Default destructor.
1918+
};
1919+
1920+
1921+
/** \brief Class of slices with default start and step values. */
1922+
template<typename IntT>
1923+
requires std::is_signed_v<IntT>
1924+
struct StopSlice : public Slice<IntT>
1925+
{
1926+
//--- Constructors / Destructor -------------------
1927+
StopSlice() noexcept = default; //!< Default constructor
1928+
1929+
inline StopSlice(const IntT stop) noexcept //!< Valued constructor
1930+
: Slice(Slice::DEFAULT, stop, 1)
1931+
{}
1932+
1933+
virtual ~StopSlice() noexcept = default; //!< Default destructor.
1934+
};
1935+
1936+
1937+
/** \brief Class of slices with default start and stop values. */
1938+
template<typename IntT>
1939+
requires std::is_signed_v<IntT>
1940+
struct StepSlice : public Slice<IntT>
1941+
{
1942+
//--- Constructors / Destructor -------------------
1943+
StepSlice() noexcept = default; //!< Default constructor
1944+
1945+
inline StepSlice(const IntT step) noexcept //!< Valued constructor
1946+
: Slice(Slice::DEFAULT, Slice::DEFAULT, step)
1947+
{}
1948+
1949+
virtual ~StepSlice() noexcept = default; //!< Default destructor.
1950+
};
1951+
1952+
1953+
/** \brief Class of slices with default step values. */
1954+
template<typename IntT>
1955+
requires std::is_signed_v<IntT>
1956+
struct StartStopSlice : public Slice<IntT>
1957+
{
1958+
//--- Constructors / Destructor -------------------
1959+
StartStopSlice() noexcept = default; //!< Default constructor
1960+
1961+
inline StartStopSlice(const IntT start, const IntT stop) noexcept //!< Valued constructor
1962+
: Slice(start, stop, 1)
1963+
{}
1964+
1965+
virtual ~StartStopSlice() noexcept = default; //!< Default destructor.
1966+
};
1967+
1968+
1969+
/** \brief Class of slices with default stop values. */
1970+
template<typename IntT>
1971+
requires std::is_signed_v<IntT>
1972+
struct StartStepSlice : public Slice<IntT>
1973+
{
1974+
//--- Constructors / Destructor -------------------
1975+
StartStepSlice() noexcept = default; //!< Default constructor
1976+
1977+
inline StartStepSlice(const IntT start, const IntT step) noexcept //!< Valued constructor
1978+
: Slice(start, Slice::DEFAULT, step)
1979+
{}
1980+
1981+
virtual ~StartStepSlice() noexcept = default; //!< Default destructor.
1982+
1983+
};
1984+
1985+
1986+
/** \brief Class of slices with default start values. */
1987+
template<typename IntT>
1988+
requires std::is_signed_v<IntT>
1989+
struct StopStepSlice : public Slice<IntT>
1990+
{
1991+
//--- Constructors / Destructor -------------------
1992+
StopStepSlice() noexcept = default; //!< Default constructor
1993+
1994+
inline StopStepSlice(const IntT stop, const IntT step) noexcept //!< Valued constructor
1995+
: Slice(Slice::DEFAULT, stop, step)
1996+
{}
1997+
1998+
virtual ~StopStepSlice() noexcept = default; //!< Default destructor.
1999+
};
2000+
2001+
17392002
//===== litteral operators ============================
17402003
/** \brief Forms a CppString literal. */
17412004
inline CppString operator""cs(const char* str, std::size_t len)

0 commit comments

Comments
 (0)