this repo has no description
at trunk 148 lines 5.7 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "api-handle.h" 3#include "bytearray-builtins.h" 4#include "bytearrayobject-utils.h" 5#include "runtime.h" 6 7namespace py { 8 9PY_EXPORT PyTypeObject* PyByteArrayIter_Type_Ptr() { 10 Runtime* runtime = Thread::current()->runtime(); 11 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 12 runtime, runtime->typeAt(LayoutId::kBytearrayIterator))); 13} 14 15char* bytearrayAsString(Runtime* runtime, ApiHandle* handle, 16 const Bytearray& array) { 17 if (void* cache = ApiHandle::cache(runtime, handle)) std::free(cache); 18 word len = array.numItems(); 19 auto buffer = static_cast<byte*>(std::malloc(len + 1)); 20 array.copyTo(buffer, len); 21 buffer[len] = '\0'; 22 ApiHandle::setCache(runtime, handle, buffer); 23 ApiHandle::setBorrowedNoImmediate(handle); 24 return reinterpret_cast<char*>(buffer); 25} 26 27PY_EXPORT char* PyByteArray_AsString(PyObject* pyobj) { 28 DCHECK(pyobj != nullptr, "null argument to PyByteArray_AsString"); 29 Thread* thread = Thread::current(); 30 HandleScope scope(thread); 31 ApiHandle* handle = ApiHandle::fromPyObject(pyobj); 32 Object obj(&scope, ApiHandle::asObject(handle)); 33 Runtime* runtime = thread->runtime(); 34 DCHECK(runtime->isInstanceOfBytearray(*obj), 35 "argument to PyByteArray_AsString is not a bytearray"); 36 Bytearray array(&scope, *obj); 37 return bytearrayAsString(runtime, handle, array); 38} 39 40PY_EXPORT int PyByteArray_CheckExact_Func(PyObject* pyobj) { 41 return ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)).isBytearray(); 42} 43 44PY_EXPORT int PyByteArray_Check_Func(PyObject* pyobj) { 45 return Thread::current()->runtime()->isInstanceOfBytearray( 46 ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 47} 48 49PY_EXPORT PyObject* PyByteArray_Concat(PyObject* a, PyObject* b) { 50 DCHECK(a != nullptr, "null argument to PyByteArray_Concat"); 51 DCHECK(b != nullptr, "null argument to PyByteArray_Concat"); 52 Thread* thread = Thread::current(); 53 HandleScope scope(thread); 54 Object left(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(a))); 55 Object right(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(b))); 56 Runtime* runtime = thread->runtime(); 57 if (!runtime->isByteslike(*left) || !runtime->isByteslike(*right)) { 58 thread->raiseWithFmt(LayoutId::kTypeError, "can't concat %T to %T", &left, 59 &right); 60 return nullptr; 61 } 62 Object result(&scope, runtime->newBytearray()); 63 result = thread->invokeFunction2(ID(operator), ID(iconcat), result, left); 64 if (result.isError()) return nullptr; 65 result = thread->invokeFunction2(ID(operator), ID(iconcat), result, right); 66 if (result.isError()) return nullptr; 67 return ApiHandle::newReferenceWithManaged(runtime, *result); 68} 69 70PY_EXPORT PyObject* PyByteArray_FromStringAndSize(const char* str, 71 Py_ssize_t size) { 72 Thread* thread = Thread::current(); 73 if (size < 0) { 74 thread->raiseWithFmt( 75 LayoutId::kSystemError, 76 "Negative size passed to PyByteArray_FromStringAndSize"); 77 return nullptr; 78 } 79 80 Runtime* runtime = thread->runtime(); 81 if (size == 0) { 82 return ApiHandle::newReferenceWithManaged(runtime, runtime->newBytearray()); 83 } 84 85 HandleScope scope(thread); 86 Bytearray result(&scope, runtime->newBytearray()); 87 if (str == nullptr) { 88 runtime->bytearrayEnsureCapacity(thread, result, size); 89 result.setNumItems(size); 90 } else { 91 runtime->bytearrayExtend(thread, result, 92 {reinterpret_cast<const byte*>(str), size}); 93 } 94 return ApiHandle::newReferenceWithManaged(runtime, *result); 95} 96 97PY_EXPORT PyObject* PyByteArray_FromObject(PyObject* obj) { 98 Thread* thread = Thread::current(); 99 Runtime* runtime = thread->runtime(); 100 if (obj == nullptr) { 101 return ApiHandle::newReferenceWithManaged(runtime, runtime->newBytearray()); 102 } 103 HandleScope scope(thread); 104 Object src(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 105 Object result(&scope, 106 thread->invokeFunction1(ID(builtins), ID(bytearray), src)); 107 return result.isError() ? nullptr : ApiHandle::newReference(runtime, *result); 108} 109 110PY_EXPORT int PyByteArray_Resize(PyObject* pyobj, Py_ssize_t newsize) { 111 DCHECK(pyobj != nullptr, "null argument to PyByteArray_Resize"); 112 DCHECK(newsize >= 0, "negative size"); 113 Thread* thread = Thread::current(); 114 HandleScope scope(thread); 115 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 116 Runtime* runtime = thread->runtime(); 117 DCHECK(runtime->isInstanceOfBytearray(*obj), 118 "argument to PyByteArray_Resize is not a bytearray"); 119 Bytearray array(&scope, *obj); 120 word requested = static_cast<word>(newsize); 121 word current = array.numItems(); 122 if (requested == current) return 0; 123 if (requested < current) { 124 array.downsize(requested); 125 } else { 126 runtime->bytearrayEnsureCapacity(thread, array, requested); 127 } 128 array.setNumItems(requested); 129 return 0; 130} 131 132PY_EXPORT Py_ssize_t PyByteArray_Size(PyObject* pyobj) { 133 DCHECK(pyobj != nullptr, "null argument to PyByteArray_Size"); 134 Thread* thread = Thread::current(); 135 HandleScope scope(thread); 136 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 137 DCHECK(thread->runtime()->isInstanceOfBytearray(*obj), 138 "argument to PyByteArray_Size is not a bytearray"); 139 return static_cast<Py_ssize_t>(Bytearray::cast(*obj).numItems()); 140} 141 142PY_EXPORT PyTypeObject* PyByteArray_Type_Ptr() { 143 Runtime* runtime = Thread::current()->runtime(); 144 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 145 runtime, runtime->typeAt(LayoutId::kBytearray))); 146} 147 148} // namespace py