1 // Copyright David Abrahams 2004. Distributed under the Boost
2 // Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 #include <boost/python/str.hpp>
5 #include <boost/python/extract.hpp>
6 #include <boost/python/ssize_t.hpp>
7
8 namespace boost { namespace python { namespace detail {
9
call(object const & arg_)10 detail::new_reference str_base::call(object const& arg_)
11 {
12 return (detail::new_reference)PyObject_CallFunction(
13 #if PY_VERSION_HEX >= 0x03000000
14 (PyObject*)&PyUnicode_Type,
15 #else
16 (PyObject*)&PyString_Type,
17 #endif
18 const_cast<char*>("(O)"),
19 arg_.ptr());
20 }
21
str_base()22 str_base::str_base()
23 : object(detail::new_reference(
24 #if PY_VERSION_HEX >= 0x03000000
25 ::PyUnicode_FromString("")
26 #else
27 ::PyString_FromString("")
28 #endif
29 ))
30 {}
31
str_base(const char * s)32 str_base::str_base(const char* s)
33 : object(detail::new_reference(
34 #if PY_VERSION_HEX >= 0x03000000
35 ::PyUnicode_FromString(s)
36 #else
37 ::PyString_FromString(s)
38 #endif
39 ))
40 {}
41
42 namespace {
43
str_size_as_py_ssize_t(std::size_t n)44 ssize_t str_size_as_py_ssize_t(std::size_t n)
45 {
46 if (n > static_cast<std::size_t>(ssize_t_max))
47 {
48 throw std::range_error("str size > ssize_t_max");
49 }
50 return static_cast<ssize_t>(n);
51 }
52
53 } // namespace <anonymous>
54
str_base(char const * start,char const * finish)55 str_base::str_base(char const* start, char const* finish)
56 : object(
57 detail::new_reference(
58 #if PY_VERSION_HEX >= 0x03000000
59 ::PyUnicode_FromStringAndSize
60 #else
61 ::PyString_FromStringAndSize
62 #endif
63 (start, str_size_as_py_ssize_t(finish - start))
64 )
65 )
66 {}
67
str_base(char const * start,std::size_t length)68 str_base::str_base(char const* start, std::size_t length) // new str
69 : object(
70 detail::new_reference(
71 #if PY_VERSION_HEX >= 0x03000000
72 ::PyUnicode_FromStringAndSize
73 #else
74 ::PyString_FromStringAndSize
75 #endif
76 ( start, str_size_as_py_ssize_t(length) )
77 )
78 )
79 {}
80
str_base(object_cref other)81 str_base::str_base(object_cref other)
82 : object(str_base::call(other))
83 {}
84
85 #define BOOST_PYTHON_FORMAT_OBJECT(z, n, data) "O"
86 #define BOOST_PYTHON_OBJECT_PTR(z, n, data) , x##n .ptr()
87
88 #define BOOST_PYTHON_DEFINE_STR_METHOD(name, arity) \
89 str str_base:: name ( BOOST_PP_ENUM_PARAMS(arity, object_cref x) ) const \
90 { \
91 return str(new_reference( \
92 expect_non_null( \
93 PyObject_CallMethod( \
94 this->ptr(), const_cast<char*>( #name ), \
95 const_cast<char*>( \
96 "(" BOOST_PP_REPEAT(arity, BOOST_PYTHON_FORMAT_OBJECT, _) ")") \
97 BOOST_PP_REPEAT_1(arity, BOOST_PYTHON_OBJECT_PTR, _))))); \
98 }
99
100 BOOST_PYTHON_DEFINE_STR_METHOD(capitalize, 0)
101 BOOST_PYTHON_DEFINE_STR_METHOD(center, 1)
102
count(object_cref sub) const103 long str_base::count(object_cref sub) const
104 {
105 return extract<long>(this->attr("count")(sub));
106 }
107
count(object_cref sub,object_cref start) const108 long str_base::count(object_cref sub, object_cref start) const
109 {
110 return extract<long>(this->attr("count")(sub,start));
111 }
112
count(object_cref sub,object_cref start,object_cref end) const113 long str_base::count(object_cref sub, object_cref start, object_cref end) const
114 {
115 return extract<long>(this->attr("count")(sub,start,end));
116 }
117
118 #if PY_VERSION_HEX < 0x03000000
decode() const119 object str_base::decode() const
120 {
121 return this->attr("decode")();
122 }
123
decode(object_cref encoding) const124 object str_base::decode(object_cref encoding) const
125 {
126 return this->attr("decode")(encoding);
127 }
128
decode(object_cref encoding,object_cref errors) const129 object str_base::decode(object_cref encoding, object_cref errors) const
130 {
131 return this->attr("decode")(encoding,errors);
132 }
133 #endif
134
encode() const135 object str_base::encode() const
136 {
137 return this->attr("encode")();
138 }
139
encode(object_cref encoding) const140 object str_base::encode(object_cref encoding) const
141 {
142 return this->attr("encode")(encoding);
143 }
144
encode(object_cref encoding,object_cref errors) const145 object str_base::encode(object_cref encoding, object_cref errors) const
146 {
147 return this->attr("encode")(encoding,errors);
148 }
149
150
151 #if PY_VERSION_HEX >= 0x03000000
152 #define _BOOST_PYTHON_ASLONG PyLong_AsLong
153 #else
154 #define _BOOST_PYTHON_ASLONG PyInt_AsLong
155 #endif
156
endswith(object_cref suffix) const157 bool str_base::endswith(object_cref suffix) const
158 {
159 bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix).ptr());
160 if (PyErr_Occurred())
161 throw_error_already_set();
162 return result;
163 }
164
endswith(object_cref suffix,object_cref start) const165 bool str_base::endswith(object_cref suffix, object_cref start) const
166 {
167 bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix,start).ptr());
168 if (PyErr_Occurred())
169 throw_error_already_set();
170 return result;
171 }
172
endswith(object_cref suffix,object_cref start,object_cref end) const173 bool str_base::endswith(object_cref suffix, object_cref start, object_cref end) const
174 {
175 bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix,start,end).ptr());
176 if (PyErr_Occurred())
177 throw_error_already_set();
178 return result;
179 }
180
181 BOOST_PYTHON_DEFINE_STR_METHOD(expandtabs, 0)
182 BOOST_PYTHON_DEFINE_STR_METHOD(expandtabs, 1)
183
find(object_cref sub) const184 long str_base::find(object_cref sub) const
185 {
186 long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub).ptr());
187 if (PyErr_Occurred())
188 throw_error_already_set();
189 return result;
190 }
191
find(object_cref sub,object_cref start) const192 long str_base::find(object_cref sub, object_cref start) const
193 {
194 long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start).ptr());
195 if (PyErr_Occurred())
196 throw_error_already_set();
197 return result;
198 }
199
find(object_cref sub,object_cref start,object_cref end) const200 long str_base::find(object_cref sub, object_cref start, object_cref end) const
201 {
202 long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start,end).ptr());
203 if (PyErr_Occurred())
204 throw_error_already_set();
205 return result;
206 }
207
index(object_cref sub) const208 long str_base::index(object_cref sub) const
209 {
210 long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub).ptr());
211 if (PyErr_Occurred())
212 throw_error_already_set();
213 return result;
214 }
215
index(object_cref sub,object_cref start) const216 long str_base::index(object_cref sub, object_cref start) const
217 {
218 long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start).ptr());
219 if (PyErr_Occurred())
220 throw_error_already_set();
221 return result;
222 }
223
index(object_cref sub,object_cref start,object_cref end) const224 long str_base::index(object_cref sub, object_cref start, object_cref end) const
225 {
226 long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start,end).ptr());
227 if (PyErr_Occurred())
228 throw_error_already_set();
229 return result;
230 }
231
isalnum() const232 bool str_base::isalnum() const
233 {
234 bool result = _BOOST_PYTHON_ASLONG(this->attr("isalnum")().ptr());
235 if (PyErr_Occurred())
236 throw_error_already_set();
237 return result;
238 }
239
isalpha() const240 bool str_base::isalpha() const
241 {
242 bool result = _BOOST_PYTHON_ASLONG(this->attr("isalpha")().ptr());
243 if (PyErr_Occurred())
244 throw_error_already_set();
245 return result;
246 }
247
isdigit() const248 bool str_base::isdigit() const
249 {
250 bool result = _BOOST_PYTHON_ASLONG(this->attr("isdigit")().ptr());
251 if (PyErr_Occurred())
252 throw_error_already_set();
253 return result;
254 }
255
islower() const256 bool str_base::islower() const
257 {
258 bool result = _BOOST_PYTHON_ASLONG(this->attr("islower")().ptr());
259 if (PyErr_Occurred())
260 throw_error_already_set();
261 return result;
262 }
263
isspace() const264 bool str_base::isspace() const
265 {
266 bool result = _BOOST_PYTHON_ASLONG(this->attr("isspace")().ptr());
267 if (PyErr_Occurred())
268 throw_error_already_set();
269 return result;
270 }
271
istitle() const272 bool str_base::istitle() const
273 {
274 bool result = _BOOST_PYTHON_ASLONG(this->attr("istitle")().ptr());
275 if (PyErr_Occurred())
276 throw_error_already_set();
277 return result;
278 }
279
isupper() const280 bool str_base::isupper() const
281 {
282 bool result = _BOOST_PYTHON_ASLONG(this->attr("isupper")().ptr());
283 if (PyErr_Occurred())
284 throw_error_already_set();
285 return result;
286 }
287
288 BOOST_PYTHON_DEFINE_STR_METHOD(join, 1)
289 BOOST_PYTHON_DEFINE_STR_METHOD(ljust, 1)
290 BOOST_PYTHON_DEFINE_STR_METHOD(lower, 0)
291 BOOST_PYTHON_DEFINE_STR_METHOD(lstrip, 0)
292 BOOST_PYTHON_DEFINE_STR_METHOD(replace, 2)
293 BOOST_PYTHON_DEFINE_STR_METHOD(replace, 3)
294
rfind(object_cref sub) const295 long str_base::rfind(object_cref sub) const
296 {
297 long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub).ptr());
298 if (PyErr_Occurred())
299 throw_error_already_set();
300 return result;
301 }
302
rfind(object_cref sub,object_cref start) const303 long str_base::rfind(object_cref sub, object_cref start) const
304 {
305 long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start).ptr());
306 if (PyErr_Occurred())
307 throw_error_already_set();
308 return result;
309 }
310
rfind(object_cref sub,object_cref start,object_cref end) const311 long str_base::rfind(object_cref sub, object_cref start, object_cref end) const
312 {
313 long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start,end).ptr());
314 if (PyErr_Occurred())
315 throw_error_already_set();
316 return result;
317 }
318
rindex(object_cref sub) const319 long str_base::rindex(object_cref sub) const
320 {
321 long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub).ptr());
322 if (PyErr_Occurred())
323 throw_error_already_set();
324 return result;
325 }
326
rindex(object_cref sub,object_cref start) const327 long str_base::rindex(object_cref sub, object_cref start) const
328 {
329 long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start).ptr());
330 if (PyErr_Occurred())
331 throw_error_already_set();
332 return result;
333 }
334
rindex(object_cref sub,object_cref start,object_cref end) const335 long str_base::rindex(object_cref sub, object_cref start, object_cref end) const
336 {
337 long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start,end).ptr());
338 if (PyErr_Occurred())
339 throw_error_already_set();
340 return result;
341 }
342
343 BOOST_PYTHON_DEFINE_STR_METHOD(rjust, 1)
344 BOOST_PYTHON_DEFINE_STR_METHOD(rstrip, 0)
345
split() const346 list str_base::split() const
347 {
348 return list(this->attr("split")());
349 }
350
split(object_cref sep) const351 list str_base::split(object_cref sep) const
352 {
353 return list(this->attr("split")(sep));
354 }
355
split(object_cref sep,object_cref maxsplit) const356 list str_base::split(object_cref sep, object_cref maxsplit) const
357 {
358 return list(this->attr("split")(sep,maxsplit));
359 }
360
splitlines() const361 list str_base::splitlines() const
362 {
363 return list(this->attr("splitlines")());
364 }
365
splitlines(object_cref keepends) const366 list str_base::splitlines(object_cref keepends) const
367 {
368 return list(this->attr("splitlines")(keepends));
369 }
370
startswith(object_cref prefix) const371 bool str_base::startswith(object_cref prefix) const
372 {
373 bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix).ptr());
374 if (PyErr_Occurred())
375 throw_error_already_set();
376 return result;
377 }
378
startswith(object_cref prefix,object_cref start) const379 bool str_base::startswith(object_cref prefix, object_cref start) const
380 {
381 bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start).ptr());
382 if (PyErr_Occurred())
383 throw_error_already_set();
384 return result;
385 }
386
startswith(object_cref prefix,object_cref start,object_cref end) const387 bool str_base::startswith(object_cref prefix, object_cref start, object_cref end) const
388 {
389 bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start,end).ptr());
390 if (PyErr_Occurred())
391 throw_error_already_set();
392 return result;
393 }
394
395 #undef _BOOST_PYTHON_ASLONG
396
397 BOOST_PYTHON_DEFINE_STR_METHOD(strip, 0)
398 BOOST_PYTHON_DEFINE_STR_METHOD(swapcase, 0)
399 BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
400 BOOST_PYTHON_DEFINE_STR_METHOD(translate, 1)
401 BOOST_PYTHON_DEFINE_STR_METHOD(translate, 2)
402 BOOST_PYTHON_DEFINE_STR_METHOD(upper, 0)
403
404 static struct register_str_pytype_ptr
405 {
register_str_pytype_ptrboost::python::detail::register_str_pytype_ptr406 register_str_pytype_ptr()
407 {
408 const_cast<converter::registration &>(
409 converter::registry::lookup(boost::python::type_id<boost::python::str>())
410 )
411 #if PY_VERSION_HEX >= 0x03000000
412 .m_class_object = &PyUnicode_Type;
413 #else
414 .m_class_object = &PyString_Type;
415 #endif
416 }
417 }register_str_pytype_ptr_;
418
419 }}} // namespace boost::python
420