|
1 |
| -# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
| 1 | +# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. |
2 | 2 | # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
3 | 3 | #
|
4 | 4 | # The Universal Permissive License (UPL), Version 1.0
|
|
37 | 37 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
38 | 38 | # SOFTWARE.
|
39 | 39 |
|
40 |
| -from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON |
| 40 | +from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare |
41 | 41 | __dir__ = __file__.rpartition("/")[0]
|
42 | 42 |
|
43 | 43 |
|
@@ -257,3 +257,83 @@ def compile_module(self, name):
|
257 | 257 | callfunction="mutate_bytes",
|
258 | 258 | cmpfunc=unhandled_error_compare
|
259 | 259 | )
|
| 260 | + |
| 261 | + test_PyBytes_Resize = CPyExtFunction( |
| 262 | + lambda args: args[0][:args[1]], |
| 263 | + lambda: ( |
| 264 | + (b"hello_beatiful_world", 5), |
| 265 | + ), |
| 266 | + code=""" |
| 267 | + PyObject* wrap_PyBytes_Resize(PyObject* bytesObj, Py_ssize_t new_size) { |
| 268 | + /* we need to create a fresh bytes object */ |
| 269 | + PyObject* res = PyBytes_FromString(PyBytes_AsString(bytesObj)); |
| 270 | + _PyBytes_Resize(&res, new_size); |
| 271 | + return res; |
| 272 | + } |
| 273 | + """, |
| 274 | + resultspec="O", |
| 275 | + argspec="On", |
| 276 | + arguments=["PyObject* bytesObj", "Py_ssize_t new_size"], |
| 277 | + callfunction="wrap_PyBytes_Resize", |
| 278 | + cmpfunc=unhandled_error_compare |
| 279 | + ) |
| 280 | + |
| 281 | + test_PyBytes_Resize_NativeStorage = CPyExtFunction( |
| 282 | + lambda args: args[1], |
| 283 | + lambda: ( |
| 284 | + (b"hello_beatiful_world", b"hello_world"), |
| 285 | + ), |
| 286 | + code=""" |
| 287 | + #include <stdio.h> |
| 288 | + |
| 289 | + /* Copies content from 'smaller' to 'larger_content' and returns a pointer to the last char. */ |
| 290 | + static char* do_pointer_arithmetics(char* larger_content, PyObject* smaller) { |
| 291 | + char* smaller_content = PyBytes_AS_STRING(smaller); |
| 292 | + Py_ssize_t smaller_len = PyBytes_Size(smaller); |
| 293 | + |
| 294 | + // 'smaller_len + 1' also contains the null byte |
| 295 | + memcpy(larger_content, smaller_content, smaller_len + 1); |
| 296 | + return larger_content + smaller_len; |
| 297 | + } |
| 298 | + |
| 299 | + PyObject* resize_bytes(PyObject* larger, PyObject* smaller) { |
| 300 | + char* data; |
| 301 | + char* dummy; |
| 302 | + char* end_ptr; |
| 303 | + Py_ssize_t len; |
| 304 | + Py_ssize_t new_len; |
| 305 | + PyObject* larger_copy; |
| 306 | + |
| 307 | + Py_INCREF(larger); |
| 308 | + Py_INCREF(smaller); |
| 309 | + |
| 310 | + /* we need to create a fresh bytes object */ |
| 311 | + larger_copy = PyBytes_FromString(PyBytes_AsString(larger)); |
| 312 | + Py_DECREF(larger); |
| 313 | + |
| 314 | + len = PyBytes_Size(larger_copy) + 1; |
| 315 | + |
| 316 | + dummy = (char*) calloc(len, sizeof(char)); |
| 317 | + data = PyBytes_AS_STRING(larger_copy); |
| 318 | + |
| 319 | + /* this will force the bytes object's content to native */ |
| 320 | + snprintf(data, len, "%s", dummy); |
| 321 | + free(dummy); |
| 322 | + |
| 323 | + /* copy smaller data and return the pointer to the last char */ |
| 324 | + end_ptr = do_pointer_arithmetics(data, smaller); |
| 325 | + Py_DECREF(smaller); |
| 326 | + |
| 327 | + /* compute new size */ |
| 328 | + new_len = (Py_ssize_t) (end_ptr - PyBytes_AS_STRING(larger_copy)); |
| 329 | + _PyBytes_Resize(&larger_copy, new_len); |
| 330 | + memcpy(PyBytes_AS_STRING(larger_copy), data, new_len * sizeof(char)); |
| 331 | + return larger_copy; |
| 332 | + } |
| 333 | + """, |
| 334 | + resultspec="O", |
| 335 | + argspec="OO", |
| 336 | + arguments=["PyObject* larger", "PyObject* smaller"], |
| 337 | + callfunction="resize_bytes", |
| 338 | + cmpfunc=unhandled_error_compare |
| 339 | + ) |
0 commit comments