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