• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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