Skip to content

Commit fef7530

Browse files
committed
bugfix : find/rfind dont return bad valid results when start/end points smaller
than the seach string are specified. Addressed github #7
1 parent aa52269 commit fef7530

File tree

2 files changed

+96
-72
lines changed

2 files changed

+96
-72
lines changed

pystring.cpp

Lines changed: 28 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -397,40 +397,6 @@ typedef int Py_ssize_t;
397397
}
398398

399399

400-
401-
//////////////////////////////////////////////////////////////////////////////////////////////
402-
///
403-
///
404-
int __adjustslicepos( std::string::size_type len_, int pos )
405-
{
406-
int len = static_cast<int>(len_);
407-
int value;
408-
409-
if ( pos < 0 )
410-
{
411-
value = len + pos;
412-
}
413-
else
414-
{
415-
value = pos;
416-
}
417-
418-
if ( value < 0 )
419-
{
420-
value = 0;
421-
}
422-
423-
else if ( value > len)
424-
{
425-
value = len;
426-
}
427-
428-
return value;
429-
430-
}
431-
432-
433-
434400
//////////////////////////////////////////////////////////////////////////////////////////////
435401
///
436402
///
@@ -860,26 +826,35 @@ typedef int Py_ssize_t;
860826

861827
}
862828

829+
//////////////////////////////////////////////////////////////////////////////////////////////
830+
///
831+
///
832+
std::string slice( const std::string & str, int start, int end )
833+
{
834+
ADJUST_INDICES(start, end, (int) str.size());
835+
if ( start >= end ) return "";
836+
return str.substr( start, end - start );
837+
}
838+
839+
863840
//////////////////////////////////////////////////////////////////////////////////////////////
864841
///
865842
///
866843
int find( const std::string & str, const std::string & sub, int start, int end )
867844
{
868-
int startp, endp;
869-
870-
startp = __adjustslicepos( str.size(), start );
871-
endp = __adjustslicepos( str.size(), end );
872-
873-
std::string::size_type result;
874-
875-
result = str.find( sub, startp );
876-
877-
if( result == std::string::npos || result >= (std::string::size_type)endp)
845+
ADJUST_INDICES(start, end, (int) str.size());
846+
847+
std::string::size_type result = str.find( sub, start );
848+
849+
// If we cannot find the string, or if the end-point of our found substring is past
850+
// the allowed end limit, return that it can't be found.
851+
if( result == std::string::npos ||
852+
(result + sub.size() > (std::string::size_type)end) )
878853
{
879854
return -1;
880855
}
881-
882-
return (int)result;
856+
857+
return (int) result;
883858
}
884859

885860
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -895,16 +870,13 @@ typedef int Py_ssize_t;
895870
///
896871
int rfind( const std::string & str, const std::string & sub, int start, int end )
897872
{
898-
int startp, endp;
899-
900-
startp = __adjustslicepos( str.size(), start );
901-
endp = __adjustslicepos( str.size(), end );
902-
903-
std::string::size_type result;
904-
905-
result = str.rfind( sub, endp );
906-
907-
if( result == std::string::npos || result < (std::string::size_type)startp )
873+
ADJUST_INDICES(start, end, (int) str.size());
874+
875+
std::string::size_type result = str.rfind( sub, end );
876+
877+
if( result == std::string::npos ||
878+
result < (std::string::size_type)start ||
879+
(result + sub.size() > (std::string::size_type)end))
908880
return -1;
909881

910882
return (int)result;
@@ -1054,22 +1026,6 @@ typedef int Py_ssize_t;
10541026

10551027
}
10561028

1057-
//////////////////////////////////////////////////////////////////////////////////////////////
1058-
///
1059-
///
1060-
std::string slice( const std::string & str, int start, int end )
1061-
{
1062-
int startp, endp;
1063-
1064-
startp = __adjustslicepos( str.size(), start );
1065-
endp = __adjustslicepos( str.size(), end );
1066-
1067-
if ( startp >= endp ) return "";
1068-
1069-
return str.substr( startp, endp - startp );
1070-
}
1071-
1072-
10731029
//////////////////////////////////////////////////////////////////////////////////////////////
10741030
///
10751031
///

test.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,19 @@ PYSTRING_ADD_TEST(pystring, find)
3636
PYSTRING_CHECK_EQUAL(pystring::find("", "a"), -1);
3737
PYSTRING_CHECK_EQUAL(pystring::find("a", ""), 0);
3838
PYSTRING_CHECK_EQUAL(pystring::find("a", "a"), 0);
39+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", ""), 0);
40+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -1), 5);
41+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -2), 4);
42+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -5), 1);
43+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -6), 0);
44+
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -7), 0);
45+
3946
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def"), 3);
4047
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", 3), 3);
4148
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", 4), -1);
4249
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", -5), 3);
4350
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", -1), -1);
51+
4452
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", -2), 7);
4553
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", -1), -1);
4654
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 0), 1);
@@ -55,6 +63,66 @@ PYSTRING_ADD_TEST(pystring, find)
5563
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, 6), 4);
5664
}
5765

66+
PYSTRING_ADD_TEST(pystring, rfind)
67+
{
68+
PYSTRING_CHECK_EQUAL(pystring::rfind("", ""), 0);
69+
PYSTRING_CHECK_EQUAL(pystring::rfind("", "a"), -1);
70+
PYSTRING_CHECK_EQUAL(pystring::rfind("a", ""), 1);
71+
PYSTRING_CHECK_EQUAL(pystring::rfind("a", "a"), 0);
72+
73+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", ""), 6);
74+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0, 1), 1);
75+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0, 5), 5);
76+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0,-1), 5);
77+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0,-3), 3);
78+
79+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def"), 3);
80+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", 3), 3);
81+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", 4), -1);
82+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", -5), 3);
83+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", -1), -1);
84+
85+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", -2), 7);
86+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", -1), -1);
87+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 0), 7);
88+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 1), 7);
89+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4), 7);
90+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 7), 7);
91+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, -5), -1);
92+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, -10), -1);
93+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, 20), 7);
94+
95+
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "abc", 6, 8), -1);
96+
}
97+
98+
PYSTRING_ADD_TEST(pystring, slice)
99+
{
100+
PYSTRING_CHECK_EQUAL(pystring::slice(""), "");
101+
PYSTRING_CHECK_EQUAL(pystring::slice("", 1), "");
102+
PYSTRING_CHECK_EQUAL(pystring::slice("", -1), "");
103+
PYSTRING_CHECK_EQUAL(pystring::slice("", -1,2), "");
104+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef"), "abcdef");
105+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",0), "abcdef");
106+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",1), "bcdef");
107+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2), "cdef");
108+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,2), "");
109+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,3), "c");
110+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,1), "");
111+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-1), "cde");
112+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-2), "cd");
113+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-3), "c");
114+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-4), "");
115+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-5), "");
116+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-1), "f");
117+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2), "ef");
118+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-99), "abcdef");
119+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-99,-98), "");
120+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2, 3), "");
121+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2, 10), "ef");
122+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-1), "f");
123+
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",0,-1), "abcde");
124+
}
125+
58126
PYSTRING_ADD_TEST(pystring, startswith)
59127
{
60128
PYSTRING_CHECK_EQUAL(pystring::startswith("", ""), true);

0 commit comments

Comments
 (0)