1package glib
2
3// #include <glib.h>
4// #include <glib-object.h>
5// #include "glib.go.h"
6import "C"
7import (
8	"unsafe"
9)
10
11/*
12 * Linked Lists
13 */
14
15// List is a representation of Glib's GList.
16type List struct {
17	list *C.struct__GList
18	// If set, dataWrap is called every time NthData()
19	// or Data() is called to wrap raw underlying
20	// value into appropriate type.
21	dataWrap func(unsafe.Pointer) interface{}
22}
23
24func WrapList(obj uintptr) *List {
25	return wrapList((*C.struct__GList)(unsafe.Pointer(obj)))
26}
27
28func wrapList(obj *C.struct__GList) *List {
29	if obj == nil {
30		return nil
31	}
32	return &List{list: obj}
33}
34
35func (v *List) wrapNewHead(obj *C.struct__GList) *List {
36	if obj == nil {
37		return nil
38	}
39	return &List{
40		list:     obj,
41		dataWrap: v.dataWrap,
42	}
43}
44
45func (v *List) Native() uintptr {
46	return uintptr(unsafe.Pointer(v.list))
47}
48
49func (v *List) native() *C.struct__GList {
50	if v == nil || v.list == nil {
51		return nil
52	}
53	return v.list
54}
55
56// DataWapper sets wrap functions, which is called during NthData()
57// and Data(). It's used to cast raw C data into appropriate
58// Go structures and types every time that data is retreived.
59func (v *List) DataWrapper(fn func(unsafe.Pointer) interface{}) {
60	if v == nil {
61		return
62	}
63	v.dataWrap = fn
64}
65
66// Append is a wrapper around g_list_append().
67func (v *List) Append(data uintptr) *List {
68	glist := C.g_list_append(v.native(), C.gpointer(data))
69	return v.wrapNewHead(glist)
70}
71
72// Prepend is a wrapper around g_list_prepend().
73func (v *List) Prepend(data uintptr) *List {
74	glist := C.g_list_prepend(v.native(), C.gpointer(data))
75	return v.wrapNewHead(glist)
76}
77
78// Insert is a wrapper around g_list_insert().
79func (v *List) Insert(data uintptr, position int) *List {
80	glist := C.g_list_insert(v.native(), C.gpointer(data), C.gint(position))
81	return v.wrapNewHead(glist)
82}
83
84// Length is a wrapper around g_list_length().
85func (v *List) Length() uint {
86	return uint(C.g_list_length(v.native()))
87}
88
89// nthDataRaw is a wrapper around g_list_nth_data().
90func (v *List) nthDataRaw(n uint) unsafe.Pointer {
91	return unsafe.Pointer(C.g_list_nth_data(v.native(), C.guint(n)))
92}
93
94// Nth() is a wrapper around g_list_nth().
95func (v *List) Nth(n uint) *List {
96	list := wrapList(C.g_list_nth(v.native(), C.guint(n)))
97	list.DataWrapper(v.dataWrap)
98	return list
99}
100
101// NthData acts the same as g_list_nth_data(), but passes
102// retrieved value before returning through wrap function, set by DataWrapper().
103// If no wrap function is set, it returns raw unsafe.Pointer.
104func (v *List) NthData(n uint) interface{} {
105	ptr := v.nthDataRaw(n)
106	if v.dataWrap != nil {
107		return v.dataWrap(ptr)
108	}
109	return ptr
110}
111
112// Free is a wrapper around g_list_free().
113func (v *List) Free() {
114	C.g_list_free(v.native())
115}
116
117// Next is a wrapper around the next struct field
118func (v *List) Next() *List {
119	return v.wrapNewHead(v.native().next)
120}
121
122// Previous is a wrapper around the prev struct field
123func (v *List) Previous() *List {
124	return v.wrapNewHead(v.native().prev)
125}
126
127// First is a wrapper around g_list_first().
128func (v *List) First() *List {
129	return v.wrapNewHead(C.g_list_first(v.native()))
130}
131
132// Last is a wrapper around g_list_last().
133func (v *List) Last() *List {
134	return v.wrapNewHead(C.g_list_last(v.native()))
135}
136
137// Reverse is a wrapper around g_list_reverse().
138func (v *List) Reverse() *List {
139	return v.wrapNewHead(C.g_list_reverse(v.native()))
140}
141
142// dataRaw is a wrapper around the data struct field
143func (v *List) dataRaw() unsafe.Pointer {
144	return unsafe.Pointer(v.native().data)
145}
146
147// Data acts the same as data struct field, but passes
148// retrieved value before returning through wrap function, set by DataWrapper().
149// If no wrap function is set, it returns raw unsafe.Pointer.
150func (v *List) Data() interface{} {
151	ptr := v.dataRaw()
152	if v.dataWrap != nil {
153		return v.dataWrap(ptr)
154	}
155	return ptr
156}
157
158// Foreach acts the same as g_list_foreach().
159// No user_data argument is implemented because of Go clojure capabilities.
160func (v *List) Foreach(fn func(item interface{})) {
161	for l := v; l != nil; l = l.Next() {
162		fn(l.Data())
163	}
164}
165
166// FreeFull acts the same as g_list_free_full().
167// Calling list.FreeFull(fn) is equivalent to calling list.Foreach(fn) and
168// list.Free() sequentially.
169func (v *List) FreeFull(fn func(item interface{})) {
170	v.Foreach(fn)
171	v.Free()
172}
173
174// CompareDataFunc is a representation of GCompareDataFunc
175type CompareDataFunc func(a, b uintptr) int
176