-
Notifications
You must be signed in to change notification settings - Fork 0
/
listimpltheight.py
107 lines (74 loc) · 2.4 KB
/
listimpltheight.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""Python 3.8 list_resize implementation"""
from math import floor
NULL = ...
Py_SSIZE_MAX = 2 ** 31
PyExc_OverflowError = OverflowError
class PyListObject:
def __init__(self):
self.ob_base = list # for fun
self.ob_size = 0
self.ob_item = []
self.allocated = 0
def append(self, obj: object) -> None:
return list_append(self, obj)
def __str__(self):
return (
f"{self.__class__.__name__}"
f"(ob_size={self.ob_size}, "
f"ob_item={self.ob_item}, "
f"allocated={self.allocated})"
)
def PyList_GET_SIZE(self: PyListObject):
"""Return the `len` of self"""
assert isinstance(self, PyListObject)
return self.ob_size
def PyList_SET_ITEM(self: PyListObject, n: int, v: object):
self.ob_item[n] = v
def PyErr_SetString(exception, msg):
raise exception(msg)
def PyErr_NoMemory():
PyErr_SetString(MemoryError, "No Memory")
def PyMem_Reaclloc(new_allocated_bytes, self):
return self.ob_item + ['*'] * (new_allocated_bytes - self.ob_size)
def list_resize(self: PyListObject, newsize: int) -> int:
allocated = self.allocated
# Bypass realloc()
if allocated >= newsize >= floor(allocated >> 1):
assert self.ob_item != NULL or newsize == 0
self.ob_size = newsize
return 0
new_allocated = newsize + floor(newsize >> 3) + (3 if newsize < 9 else 6)
if new_allocated > Py_SSIZE_MAX / 1: # assume PyObject pointer is 1 byte
PyErr_NoMemory()
return -1
if newsize == 0:
new_allocated = 0
if new_allocated <= Py_SSIZE_MAX / 1:
new_allocated_bytes = new_allocated * 1
items = PyMem_Reaclloc(new_allocated_bytes, self)
else:
items = NULL
if items == NULL:
PyErr_NoMemory()
return -1
self.ob_item = items
self.ob_size = newsize
self.allocated = new_allocated
return 0
def app1(self: PyListObject, v: object):
n = PyList_GET_SIZE(self)
assert v != NULL
if n == Py_SSIZE_MAX:
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to list")
return -1
if list_resize(self, n + 1) < 0:
return -1
PyList_SET_ITEM(self, n, v)
return 0
def list_append(self: PyListObject, obj: object):
if app1(self, obj) == 0:
return None
return NULL
lst = PyListObject()
lst.append('Py 3.8')