this repo has no description
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