Commit a46ed3f4 authored by Janek Bevendorff's avatar Janek Bevendorff Committed by GitHub

Fix "std::string::npos" in 'libcpp.string' and add missing C++ string methods (GH-4276)

Closes https://github.com/cython/cython/issues/4268
parent fae33cf7
...@@ -2,16 +2,15 @@ ...@@ -2,16 +2,15 @@
# deprecated cimport for backwards compatibility: # deprecated cimport for backwards compatibility:
from libc.string cimport const_char from libc.string cimport const_char
cdef extern from "<string>" namespace "std::string" nogil:
const size_t npos
cdef extern from "<string>" namespace "std" nogil: cdef extern from "<string>" namespace "std" nogil:
size_t npos = -1
cdef cppclass string: cdef cppclass string:
cppclass iterator: cppclass iterator:
iterator() iterator()
char& operator*() char& operator*()
iterator(iterator &) iterator(iterator&)
iterator operator++() iterator operator++()
iterator operator--() iterator operator--()
bint operator==(iterator) bint operator==(iterator)
...@@ -34,12 +33,12 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -34,12 +33,12 @@ cdef extern from "<string>" namespace "std" nogil:
pass pass
string() except + string() except +
string(const char *) except + string(const string& s) except +
string(const char *, size_t) except + string(const string& s, size_t pos) except +
string(const string&) except + string(const string& s, size_t pos, size_t len) except +
# as a string formed by a repetition of character c, n times. string(const char* s) except +
string(size_t, char) except + string(const char* s, size_t n) except +
# from a pair of iterators string(size_t n, char c) except +
string(iterator first, iterator last) except + string(iterator first, iterator last) except +
iterator begin() iterator begin()
...@@ -56,111 +55,122 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -56,111 +55,122 @@ cdef extern from "<string>" namespace "std" nogil:
size_t size() size_t size()
size_t max_size() size_t max_size()
size_t length() size_t length()
void resize(size_t) void resize(size_t) except +
void resize(size_t, char c) void resize(size_t, char) except +
void shrink_to_fit() except +
size_t capacity() size_t capacity()
void reserve(size_t) void reserve(size_t) except +
void clear() void clear()
bint empty() bint empty()
iterator erase(iterator position)
iterator erase(const_iterator position)
iterator erase(iterator first, iterator last) iterator erase(iterator first, iterator last)
iterator erase(iterator p)
iterator erase(const_iterator first, const_iterator last) iterator erase(const_iterator first, const_iterator last)
iterator erase(const_iterator p)
char& at(size_t) except + string& erase(size_t pos, size_t len) except +
char& operator[](size_t) string& erase(size_t pos) except +
char& front() # C++11 string& erase() except +
char& back() # C++11
int compare(const string&) char& at(size_t pos) except +
char& operator[](size_t pos)
string& append(const string&) except + char& front()
string& append(const string&, size_t, size_t) except + char& back()
string& append(const char *) except + int compare(const string& s)
string& append(const char *, size_t) except + int compare(size_t pos, size_t len, const string& s) except +
string& append(size_t, char) except + int compare(size_t pos, size_t len, const string& s, size_t subpos, size_t sublen) except +
int compare(const char* s) except +
int compare(size_t pos, size_t len, const char* s) except +
int compare(size_t pos, size_t len, const char* s , size_t n) except +
string& append(const string& s) except +
string& append(const string& s, size_t subpos, size_t sublen) except +
string& append(const char* s) except +
string& append(const char* s, size_t n) except +
string& append(size_t n, char c) except +
void push_back(char c) except + void push_back(char c) except +
void pop_back()
string& assign (const string&)
string& assign (const string&, size_t, size_t) string& assign (const string& s) except +
string& assign (const char *, size_t) string& assign (const string& s, size_t subpos, size_t sublen) except +
string& assign (const char *) string& assign (const char* s, size_t n) except +
string& assign (size_t n, char c) string& assign (const char* s) except +
string& assign (size_t n, char c) except +
string& insert(size_t, const string&) except +
string& insert(size_t, const string&, size_t, size_t) except + string& insert(size_t pos, const string& s, size_t subpos, size_t sublen) except +
string& insert(size_t, const char* s, size_t) except + string& insert(size_t pos, const string& s) except +
string& insert(size_t pos, const char* s, size_t n) except +
string& insert(size_t pos, const char* s) except +
string& insert(size_t, const char* s) except + string& insert(size_t pos, size_t n, char c) except +
string& insert(size_t, size_t, char c) except + void insert(iterator p, size_t n, char c) except +
iterator insert(iterator p, char c) except +
size_t copy(char *, size_t, size_t) except +
size_t copy(char* s, size_t len, size_t pos) except +
size_t find(const string&, size_t pos) size_t copy(char* s, size_t len) except +
size_t find(const string&)
size_t find(const char*, size_t pos, size_t n) size_t find(const string& s, size_t pos)
size_t find(const char*, size_t pos) size_t find(const string& s)
size_t find(const char*) size_t find(const char* s, size_t pos, size_t n)
size_t find(const char* s, size_t pos)
size_t find(const char* s)
size_t find(char c, size_t pos) size_t find(char c, size_t pos)
size_t find(char c) size_t find(char c)
size_t rfind(const string&, size_t pos) size_t rfind(const string&, size_t pos)
size_t rfind(const string&) size_t rfind(const string&)
size_t rfind(const char* s, size_t pos, size_t n) size_t rfind(const char* s, size_t pos, size_t n)
size_t rfind(const char*, size_t pos) size_t rfind(const char* s, size_t pos)
size_t rfind(const char*) size_t rfind(const char* s)
size_t rfind(char c, size_t pos) size_t rfind(char c, size_t pos)
size_t rfind(char c) size_t rfind(char c)
size_t find_first_of(const string&, size_t pos) size_t find_first_of(const string&, size_t pos)
size_t find_first_of(const string&) size_t find_first_of(const string&)
size_t find_first_of(const char* s, size_t pos, size_t n) size_t find_first_of(const char* s, size_t pos, size_t n)
size_t find_first_of(const char*, size_t pos) size_t find_first_of(const char* s, size_t pos)
size_t find_first_of(const char*) size_t find_first_of(const char* s)
size_t find_first_of(char c, size_t pos) size_t find_first_of(char c, size_t pos)
size_t find_first_of(char c) size_t find_first_of(char c)
size_t find_first_not_of(const string&, size_t pos) size_t find_first_not_of(const string& s, size_t pos)
size_t find_first_not_of(const string&) size_t find_first_not_of(const string& s)
size_t find_first_not_of(const char* s, size_t, size_t) size_t find_first_not_of(const char* s, size_t pos, size_t n)
size_t find_first_not_of(const char*, size_t pos) size_t find_first_not_of(const char* s, size_t pos)
size_t find_first_not_of(const char*) size_t find_first_not_of(const char*)
size_t find_first_not_of(char c, size_t pos) size_t find_first_not_of(char c, size_t pos)
size_t find_first_not_of(char c) size_t find_first_not_of(char c)
size_t find_last_of(const string&, size_t pos) size_t find_last_of(const string& s, size_t pos)
size_t find_last_of(const string&) size_t find_last_of(const string& s)
size_t find_last_of(const char* s, size_t pos, size_t n) size_t find_last_of(const char* s, size_t pos, size_t n)
size_t find_last_of(const char*, size_t pos) size_t find_last_of(const char* s, size_t pos)
size_t find_last_of(const char*) size_t find_last_of(const char* s)
size_t find_last_of(char c, size_t pos) size_t find_last_of(char c, size_t pos)
size_t find_last_of(char c) size_t find_last_of(char c)
size_t find_last_not_of(const string&, size_t pos) size_t find_last_not_of(const string& s, size_t pos)
size_t find_last_not_of(const string&) size_t find_last_not_of(const string& s)
size_t find_last_not_of(const char* s, size_t pos, size_t n) size_t find_last_not_of(const char* s, size_t pos, size_t n)
size_t find_last_not_of(const char*, size_t pos) size_t find_last_not_of(const char* s, size_t pos)
size_t find_last_not_of(const char*) size_t find_last_not_of(const char* s)
size_t find_last_not_of(char c, size_t pos) size_t find_last_not_of(char c, size_t pos)
size_t find_last_not_of(char c) size_t find_last_not_of(char c)
string substr(size_t, size_t) except + string substr(size_t pos, size_t len) except +
string substr(size_t pos) except +
string substr() string substr()
string substr(size_t) except +
#string& operator= (const string&) #string& operator= (const string&)
#string& operator= (const char*) #string& operator= (const char*)
#string& operator= (char) #string& operator= (char)
string operator+ (const string& rhs) except + string operator+ (const string&) except +
string operator+ (const char* rhs) except + string operator+ (const char*) except +
bint operator==(const string&) bint operator==(const string&)
bint operator==(const char*) bint operator==(const char*)
bint operator!= (const string& rhs ) bint operator!= (const string&)
bint operator!= (const char* ) bint operator!= (const char*)
bint operator< (const string&) bint operator< (const string&)
bint operator< (const char*) bint operator< (const char*)
...@@ -175,12 +185,38 @@ cdef extern from "<string>" namespace "std" nogil: ...@@ -175,12 +185,38 @@ cdef extern from "<string>" namespace "std" nogil:
bint operator>= (const char*) bint operator>= (const char*)
string to_string(int val) string to_string(int val) except +
string to_string(long val) string to_string(long val) except +
string to_string (long long val) string to_string(long long val) except +
string to_string (unsigned val) string to_string(unsigned val) except +
string to_string (unsigned long val) string to_string(size_t val) except +
string to_string (unsigned long long val) string to_string(ssize_t val) except +
string to_string (float val) string to_string(unsigned long val) except +
string to_string (double val) string to_string(unsigned long long val) except +
string to_string (long double val) string to_string(float val) except +
string to_string(double val) except +
string to_string(long double val) except +
int stoi(const string& s, size_t* idx, int base) except +
int stoi(const string& s, size_t* idx) except +
int stoi(const string& s) except +
long stol(const string& s, size_t* idx, int base) except +
long stol(const string& s, size_t* idx) except +
long stol(const string& s) except +
long long stoll(const string& s, size_t* idx, int base) except +
long long stoll(const string& s, size_t* idx) except +
long long stoll(const string& s) except +
unsigned long stoul(const string& s, size_t* idx, int base) except +
unsigned long stoul(const string& s, size_t* idx) except +
unsigned long stoul(const string& s) except +
unsigned long long stoull(const string& s, size_t* idx, int base) except +
unsigned long long stoull(const string& s, size_t* idx) except +
unsigned long long stoull(const string& s) except +
float stof(const string& s, size_t* idx) except +
float stof(const string& s) except +
double stod(const string& s, size_t* idx) except +
double stod(const string& s) except +
long double stold(const string& s, size_t* idx) except +
long double stold(const string& s) except +
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
cimport cython cimport cython
from libcpp.string cimport string, to_string from libcpp.string cimport string, npos, to_string, stoi, stof
b_asdf = b'asdf' b_asdf = b'asdf'
b_asdg = b'asdg' b_asdg = b'asdg'
...@@ -102,6 +102,15 @@ def test_push_back(char *a): ...@@ -102,6 +102,15 @@ def test_push_back(char *a):
s.push_back(<char>ord('s')) s.push_back(<char>ord('s'))
return s.c_str() return s.c_str()
def test_pop_back(char *a):
"""
>>> test_pop_back(b'abc') == b'ab' or test_pop_back(b'abc')
True
"""
cdef string s = string(a)
s.pop_back()
return s
def test_insert(char *a, char *b, int i): def test_insert(char *a, char *b, int i):
""" """
>>> test_insert('AAAA'.encode('ASCII'), 'BBBB'.encode('ASCII'), 2) == 'AABBBBAA'.encode('ASCII') >>> test_insert('AAAA'.encode('ASCII'), 'BBBB'.encode('ASCII'), 2) == 'AABBBBAA'.encode('ASCII')
...@@ -133,6 +142,17 @@ def test_find(char *a, char *b): ...@@ -133,6 +142,17 @@ def test_find(char *a, char *b):
cdef size_t i = s.find(t) cdef size_t i = s.find(t)
return i return i
def test_npos(char *a, char *b):
"""
>>> test_npos(b'abc', b'x')
True
>>> test_npos(b'abc', b'a')
False
"""
cdef string s = string(a)
cdef string st = string(b)
return s.find(st) == npos
def test_clear(): def test_clear():
""" """
>>> test_clear() == ''.encode('ASCII') >>> test_clear() == ''.encode('ASCII')
...@@ -142,6 +162,18 @@ def test_clear(): ...@@ -142,6 +162,18 @@ def test_clear():
s.clear() s.clear()
return s.c_str() return s.c_str()
def test_erase(char *a, size_t pos=0, size_t count=npos):
"""
>>> test_erase(b'abc') == b'' or test_erase(b'abc')
True
>>> test_erase(b'abc', 1) == b'a' or test_erase(b'abc', 1)
True
>>> test_erase(b'abc', 1, 1) == b'ac' or test_erase(b'abc', 1, 1)
True
"""
cdef string s = string(a)
return s.erase(pos, count)
def test_assign(char *a): def test_assign(char *a):
""" """
>>> test_assign(b_asdf) == 'ggg'.encode('ASCII') >>> test_assign(b_asdf) == 'ggg'.encode('ASCII')
...@@ -345,18 +377,34 @@ def test_iteration(string s): ...@@ -345,18 +377,34 @@ def test_iteration(string s):
""" """
return [c for c in s] return [c for c in s]
def test_to_string(x): def test_to_string(x):
""" """
>>> print(test_to_string(5)) >>> print(test_to_string(5))
si=5 sl=5 si=5 sl=5 ss=5 sss=5
>>> print(test_to_string(-5)) >>> print(test_to_string(-5))
si=-5 sl=-5 si=-5 sl=-5 ss=5 sss=-5
""" """
si = to_string(<int>x).decode('ascii') si = to_string(<int>x).decode('ascii')
sl = to_string(<long>x).decode('ascii') sl = to_string(<long>x).decode('ascii')
return f"si={si} sl={sl}" ss = to_string(<size_t>abs(x)).decode('ascii')
sss = to_string(<ssize_t>x).decode('ascii')
return f"si={si} sl={sl} ss={ss} sss={sss}"
def test_stoi(char *a):
"""
>>> test_stoi(b'5')
5
"""
cdef string s = string(a)
return stoi(s)
def test_stof(char *a):
"""
>>> test_stof(b'5.5')
5.5
"""
cdef string s = string(a)
return stof(s)
_WARNINGS = """ _WARNINGS = """
21:31: Cannot pass Python object as C++ data structure reference (string &), will pass by copy. 21:31: Cannot pass Python object as C++ data structure reference (string &), will pass by copy.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment