@@ -1072,62 +1072,47 @@ namespace pcs // i.e. "pythonic c++ strings"
10721072 * and negative start or stop is relative to the end of the
10731073 * string.
10741074 * Notice: the stop value specifies an out of bounds index.
1075+ * \see class Slice and all its inheriting classes.
10751076 */
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- }
1077+ template <typename IntT>
1078+ requires std::is_signed_v<IntT>
1079+ CppStringT operator () (Slice<IntT> slice) const noexcept
1080+ {
1081+ // optimization on 1 by 1 step
1082+ if (slice.step () == 1 ) {
1083+ slice.begin (*this );
1084+ if (slice.start () < slice.stop ())
1085+ return this ->substr (slice.start (), slice.stop () - slice.start () + 1 );
1086+ else
1087+ return CppStringT ();
1088+ }
10941089
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- {
10981090 CppStringT res{};
10991091
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- }
1092+ // optimization on reversed 1 by 1 step
1093+ if (slice.step () == -1 ) {
1094+ slice.begin (*this );
1095+ if (slice.stop () < slice.start ()) {
1096+ res = this ->substr (slice.stop (), slice.start () - slice.stop () + 1 );
1097+ std::ranges::reverse (res); // notice: may use vectorization if available
1098+ }
1099+ return res;
11251100 }
11261101
1102+ // finally, no trivial optimization -- and naive implementation...
1103+ for (slice.begin (*this ); !slice.end (); ++slice)
1104+ res += (*this )[*slice];
1105+
11271106 return res;
11281107 }
11291108
1130-
1109+ /* * \brief Generates a new string according to the specified slicing values. */
1110+ inline CppStringT operator () (const long long start, const long long stop, const long long step = 1 ) const noexcept
1111+ {
1112+ Slice<long long > slice (start, stop, step);
1113+ return (*this )(slice);
1114+ }
1115+
11311116
11321117 // --- operator * --------------------------------------
11331118 /* * \brief Generates a new string with count times the content of this string. */
@@ -1888,6 +1873,11 @@ namespace pcs // i.e. "pythonic c++ strings"
18881873 return _index;
18891874 }
18901875
1876+ // --- properties ----------------------------------
1877+ inline IntT start () { return _start; } // !< Returns the start index of this slide
1878+ inline IntT stop () { return _stop; } // !< Returns the stop index of this slide
1879+ inline IntT step () { return _step; } // !< Returns the step value of this slide
1880+
18911881
18921882 private:
18931883 IntT _start{ 0 };
@@ -1898,15 +1888,21 @@ namespace pcs // i.e. "pythonic c++ strings"
18981888
18991889 const IntT _prepare_iterating (const IntT str_size) noexcept
19001890 {
1901- if (_start == DEFAULT)
1902- _start = 0 ;
1891+ if (_start == DEFAULT) {
1892+ if (_step < 0 && _step != DEFAULT)
1893+ _start = str_size - 1 ;
1894+ else
1895+ _start = 0 ;
1896+ }
19031897 else if (_start < 0 ) {
19041898 _start += str_size;
19051899 if (_start < 0 )
19061900 _start = 0 ;
19071901 }
1908- else if (_start >= str_size)
1909- _start = str_size - 1 ;
1902+ else if (_start >= str_size) {
1903+ if (_step < 0 && _step != DEFAULT)
1904+ _start = str_size - 1 ;
1905+ }
19101906
19111907 if (_stop == DEFAULT) {
19121908 if (_step < 0 && _step != DEFAULT)
0 commit comments