-
Notifications
You must be signed in to change notification settings - Fork 9
/
list.go
160 lines (139 loc) · 4.28 KB
/
list.go
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2011 Julian Phillips. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package py
// #include "utils.h"
// static inline int listCheck(PyObject *o) { return PyList_Check(o); }
// static inline int listCheckE(PyObject *o) { return PyList_CheckExact(o); }
import "C"
import (
"fmt"
"unsafe"
)
// *List represents a Python list. In addition to satisfying the Object
// interface, List pointers also have a number of methods defined - representing
// the PyList_XXX functions from the Python C API.
type List struct {
AbstractObject
o C.PyListObject
}
// ListType is the Type object that represents the List type.
var ListType = (*Type)(unsafe.Pointer(C.getBasePyType(C.GoPyList_Type)))
func listCheck(obj Object) bool {
return C.listCheck(c(obj)) != 0
}
func newList(obj *C.PyObject) *List {
return (*List)(unsafe.Pointer(obj))
}
// NewList creates a new Python List instance. The created list has initial
// length "size".
//
// Note: If size > 0, then the objects in the returned list are initialised to
// nil. Thus you cannot use Abstract API functions, or expose the object to
// Python code without first filling in all the created slots with
// list.SetItem().
//
// Return value: New Reference.
func NewList(size int64) (*List, error) {
ret := C.PyList_New(C.Py_ssize_t(size))
if ret == nil {
return nil, exception()
}
return newList(ret), nil
}
// CheckExact returns true if if l is an actual Python list, and not a sub type.
func (l *List) CheckExact() bool {
ret := C.listCheckE(c(l))
if int(ret) != 0 {
return true
}
return false
}
// Size returns the number of elements in the list l. This is equivalent to the
// Python "len(l)".
func (l *List) Size() int64 {
ret := C.PyList_Size(c(l))
if ret < 0 {
panic(exception())
}
return int64(ret)
}
// GetItem returns the Object contained in list l at index idx. If idx is out
// of bounds for l, then an IndexError will be returned.
//
// Return value: Borrowed Reference.
func (l *List) GetItem(idx int64) (Object, error) {
ret := C.PyList_GetItem(c(l), C.Py_ssize_t(idx))
return obj2ObjErr(ret)
}
// SetItem sets the Object at index idx in list l to Object obj.
//
// Note: This method "steals" a reference to obj, and discards a reference to
// the current value of idx in l (if there is one).
func (l *List) SetItem(idx int64, obj Object) error {
ret := C.PyList_SetItem(c(l), C.Py_ssize_t(idx), c(obj))
return int2Err(ret)
}
// Insert adds the Object obj to list l, by inserting it before the value
// currently stored at index idx (making obj the new value with index idx).
// This is equivalent to the Python "l.insert(idx, obj)".
func (l *List) Insert(idx int64, obj Object) error {
ret := C.PyList_Insert(c(l), C.Py_ssize_t(idx), c(obj))
return int2Err(ret)
}
// Append adds the Object obj to list l, by appending it to the end of the list.
// This is equivalent to the Python "l.append(obj)"
func (l *List) Append(obj Object) error {
ret := C.PyList_Append(c(l), c(obj))
return int2Err(ret)
}
func (l *List) GetSlice(low, high int64) (*List, error) {
ret := C.PyList_GetSlice(c(l), C.Py_ssize_t(low), C.Py_ssize_t(high))
if ret == nil {
return nil, exception()
}
return newList(ret), nil
}
func (l *List) SetSlice(low, high int64, items *List) error {
ret := C.PyList_SetSlice(c(l), C.Py_ssize_t(low), C.Py_ssize_t(high), c(items))
return int2Err(ret)
}
func (l *List) Sort() error {
ret := C.PyList_Sort(c(l))
return int2Err(ret)
}
func (l *List) Reverse() error {
ret := C.PyList_Reverse(c(l))
return int2Err(ret)
}
func (l *List) Tuple() *Tuple {
ret := C.PyList_AsTuple(c(l))
if ret == nil {
panic(exception())
}
return newTuple(ret)
}
// Slice returns the list l as a Go Object slice. The order of objects is
// copied from the Python list, but changes to the slice are not reflected in
// the Python list.
//
// Note: The returned slice contains borrowed references to the values.
func (l *List) Slice() []Object {
size := l.Size()
s := make([]Object, size)
for i := int64(0); i < size; i++ {
o, err := l.GetItem(i)
if err != nil {
panic(err)
}
s[i] = o
}
return s
}
// String returns a string representation of the list l.
func (l *List) String() string {
if l == nil {
return "<nil>"
}
return fmt.Sprintf("%v", l.Slice())
}