From 8dee7f91b29c3eb1574f86eac63ecd1e4a31f993 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Tue, 13 Jul 2021 21:20:37 +0200 Subject: Fix "std::string::npos" in 'libcpp.string' and add missing C++ string methods (GH-4276) Closes https://github.com/cython/cython/issues/4268 --- Cython/Includes/libcpp/string.pxd | 223 +++++++++++++++++++++++++------------- tests/run/cpp_stl_string.pyx | 66 ++++++++++- 2 files changed, 211 insertions(+), 78 deletions(-) diff --git a/Cython/Includes/libcpp/string.pxd b/Cython/Includes/libcpp/string.pxd index 503e664a8..a894144f1 100644 --- a/Cython/Includes/libcpp/string.pxd +++ b/Cython/Includes/libcpp/string.pxd @@ -2,27 +2,21 @@ # deprecated cimport for backwards compatibility: from libc.string cimport const_char +cdef extern from "" namespace "std::string" nogil: + const size_t npos cdef extern from "" namespace "std" nogil: - - size_t npos = -1 - cdef cppclass string: - string() except + - string(const char *) except + - string(const char *, size_t) except + - string(const string&) except + - # as a string formed by a repetition of character c, n times. - string(size_t, char) except + cppclass iterator: iterator() char& operator*() - iterator(iterator &) + iterator(iterator&) iterator operator++() iterator operator--() bint operator==(iterator) bint operator!=(iterator) + cppclass reverse_iterator: char& operator*() iterator operator++() @@ -35,11 +29,22 @@ cdef extern from "" namespace "std" nogil: bint operator>(reverse_iterator) bint operator<=(reverse_iterator) bint operator>=(reverse_iterator) + cppclass const_iterator(iterator): pass + cppclass const_reverse_iterator(reverse_iterator): pass + string() except + + string(const string& s) except + + string(const string& s, size_t pos) except + + string(const string& s, size_t pos, size_t len) except + + string(const char* s) except + + string(const char* s, size_t n) except + + string(size_t n, char c) except + + string(iterator first, iterator last) except + + iterator begin() const_iterator const_begin "begin"() iterator end() @@ -54,96 +59,123 @@ cdef extern from "" namespace "std" nogil: size_t size() size_t max_size() size_t length() - void resize(size_t) - void resize(size_t, char c) + void resize(size_t) except + + void resize(size_t, char) except + + void shrink_to_fit() except + size_t capacity() - void reserve(size_t) + void reserve(size_t) except + void clear() bint empty() - char& at(size_t) - char& operator[](size_t) - char& front() # C++11 - char& back() # C++11 - int compare(const string&) - - string& append(const string&) - string& append(const string&, size_t, size_t) - string& append(const char *) - string& append(const char *, size_t) - string& append(size_t, char) - - void push_back(char c) - - string& assign (const string&) - string& assign (const string&, size_t, size_t) - string& assign (const char *, size_t) - string& assign (const char *) - string& assign (size_t n, char c) - - string& insert(size_t, const string&) - string& insert(size_t, const string&, size_t, size_t) - string& insert(size_t, const char* s, size_t) - - - string& insert(size_t, const char* s) - string& insert(size_t, size_t, char c) - - size_t copy(char *, size_t, size_t) - - size_t find(const string&) - size_t find(const string&, size_t) - size_t find(const char*, size_t pos, size_t) - size_t find(const char*, size_t pos) - size_t find(char, size_t pos) - - size_t rfind(const string&, size_t) - size_t rfind(const char* s, size_t, size_t) - size_t rfind(const char*, size_t pos) - size_t rfind(char c, size_t) + iterator erase(iterator first, iterator last) + iterator erase(iterator p) + iterator erase(const_iterator first, const_iterator last) + iterator erase(const_iterator p) + string& erase(size_t pos, size_t len) except + + string& erase(size_t pos) except + + string& erase() except + + + char& at(size_t pos) except + + char& operator[](size_t pos) + char& front() + char& back() + int compare(const string& s) + int compare(size_t pos, size_t len, const string& s) 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 pop_back() + + string& assign(const string& s) except + + string& assign(const string& s, size_t subpos, size_t sublen) except + + string& assign(const char* s, size_t n) except + + string& assign(const char* s) except + + string& assign(size_t n, char c) except + + + string& insert(size_t pos, const string& s, size_t subpos, size_t sublen) 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 pos, size_t n, char c) except + + void insert(iterator p, size_t n, char c) except + + iterator insert(iterator p, char c) except + + + size_t copy(char* s, size_t len, size_t pos) except + + size_t copy(char* s, size_t len) except + + + size_t find(const string& s, size_t pos) + size_t find(const string& s) + 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 rfind(const string&, size_t pos) + 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 rfind(const char* s) + size_t rfind(char c, size_t pos) size_t rfind(char c) - size_t find_first_of(const string&, size_t) - size_t find_first_of(const char* s, size_t, size_t) - size_t find_first_of(const char*, size_t pos) - size_t find_first_of(char c, size_t) + size_t find_first_of(const string&, size_t pos) + 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 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 find_first_not_of(const string&, size_t) - size_t find_first_not_of(const char* s, size_t, size_t) - size_t find_first_not_of(const char*, size_t pos) - size_t find_first_not_of(char c, size_t) + size_t find_first_not_of(const string& s, size_t pos) + size_t find_first_not_of(const string& s) + size_t find_first_not_of(const char* s, size_t pos, size_t n) + 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(char c, size_t pos) size_t find_first_not_of(char c) - size_t find_last_of(const string&, size_t) - size_t find_last_of(const char* s, size_t, size_t) - size_t find_last_of(const char*, size_t pos) - size_t find_last_of(char c, size_t) + size_t find_last_of(const string& s, size_t pos) + 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 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 find_last_not_of(const string&, size_t) - size_t find_last_not_of(const char* s, size_t, size_t) - size_t find_last_not_of(const char*, size_t pos) + size_t find_last_not_of(const string& s, size_t pos) + 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 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) - string substr(size_t, size_t) + string substr(size_t pos, size_t len) except + + string substr(size_t pos) except + string substr() - string substr(size_t) - - size_t find_last_not_of(char c, size_t) - size_t find_last_not_of(char c) #string& operator= (const string&) #string& operator= (const char*) #string& operator= (char) - string operator+ (const string& rhs) - string operator+ (const char* rhs) + string operator+ (const string&) except + + string operator+ (const char*) except + bint operator==(const string&) bint operator==(const char*) - bint operator!= (const string& rhs ) - bint operator!= (const char* ) + bint operator!= (const string&) + bint operator!= (const char*) bint operator< (const string&) bint operator< (const char*) @@ -156,3 +188,40 @@ cdef extern from "" namespace "std" nogil: bint operator>= (const string&) bint operator>= (const char*) + + + string to_string(int val) except + + string to_string(long val) except + + string to_string(long long val) except + + string to_string(unsigned val) except + + string to_string(size_t val) except + + string to_string(ssize_t val) except + + string to_string(unsigned long val) except + + string to_string(unsigned long long val) except + + 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 + diff --git a/tests/run/cpp_stl_string.pyx b/tests/run/cpp_stl_string.pyx index 1f9385247..521085bfc 100644 --- a/tests/run/cpp_stl_string.pyx +++ b/tests/run/cpp_stl_string.pyx @@ -3,7 +3,7 @@ cimport cython -from libcpp.string cimport string +from libcpp.string cimport string, npos, to_string, stoi, stof b_asdf = b'asdf' b_asdg = b'asdg' @@ -102,6 +102,15 @@ def test_push_back(char *a): s.push_back(ord('s')) 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): """ >>> test_insert('AAAA'.encode('ASCII'), 'BBBB'.encode('ASCII'), 2) == 'AABBBBAA'.encode('ASCII') @@ -133,6 +142,17 @@ def test_find(char *a, char *b): cdef size_t i = s.find(t) 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(): """ >>> test_clear() == ''.encode('ASCII') @@ -142,6 +162,18 @@ def test_clear(): s.clear() 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): """ >>> test_assign(b_asdf) == 'ggg'.encode('ASCII') @@ -346,6 +378,38 @@ def test_iteration(string s): return [c for c in s] +def test_to_string(x): + """ + >>> print(test_to_string(5)) + si=5 sl=5 ss=5 sss=5 + >>> print(test_to_string(-5)) + si=-5 sl=-5 ss=5 sss=-5 + """ + si = to_string(x).decode('ascii') + sl = to_string(x).decode('ascii') + ss = to_string(abs(x)).decode('ascii') + sss = to_string(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 = """ 21:31: Cannot pass Python object as C++ data structure reference (string &), will pass by copy. """ -- cgit v1.2.1