1package glib
2
3// #include <glib.h>
4// #include <glib-object.h>
5// #include "glib.go.h"
6import "C"
7import "unsafe"
8
9// SList is a representation of Glib's GSList. A SList must be manually freed
10// by either calling Free() or FreeFull()
11type SList struct {
12	list *C.struct__GSList
13	// If set, dataWrap is called every time Data()
14	// is called to wrap raw underlying
15	// value into appropriate type.
16	dataWrap func(unsafe.Pointer) interface{}
17}
18
19func WrapSList(obj uintptr) *SList {
20	return wrapSList((*C.struct__GSList)(unsafe.Pointer(obj)))
21}
22
23func wrapSList(obj *C.struct__GSList) *SList {
24	if obj == nil {
25		return nil
26	}
27
28	//NOTE a list should be freed by calling either
29	//g_slist_free() or g_slist_free_full(). However, it's not possible to use a
30	//finalizer for this.
31	return &SList{list: obj}
32}
33
34func (v *SList) wrapNewHead(obj *C.struct__GSList) *SList {
35	if obj == nil {
36		return nil
37	}
38	return &SList{
39		list:     obj,
40		dataWrap: v.dataWrap,
41	}
42}
43
44func (v *SList) Native() uintptr {
45	return uintptr(unsafe.Pointer(v.list))
46}
47
48func (v *SList) native() *C.struct__GSList {
49	if v == nil || v.list == nil {
50		return nil
51	}
52	return v.list
53}
54
55// DataWapper sets wrap functions, which is called during NthData()
56// and Data(). It's used to cast raw C data into appropriate
57// Go structures and types every time that data is retreived.
58func (v *SList) DataWrapper(fn func(unsafe.Pointer) interface{}) {
59	if v == nil {
60		return
61	}
62	v.dataWrap = fn
63}
64
65func (v *SList) Append(data uintptr) *SList {
66	ret := C.g_slist_append(v.native(), C.gpointer(data))
67	if ret == v.native() {
68		return v
69	}
70
71	return wrapSList(ret)
72}
73
74// Length is a wrapper around g_slist_length().
75func (v *SList) Length() uint {
76	return uint(C.g_slist_length(v.native()))
77}
78
79// Next is a wrapper around the next struct field
80func (v *SList) Next() *SList {
81	n := v.native()
82	if n == nil {
83		return nil
84	}
85
86	return wrapSList(n.next)
87}
88
89// dataRaw is a wrapper around the data struct field
90func (v *SList) dataRaw() unsafe.Pointer {
91	n := v.native()
92	if n == nil {
93		return nil
94	}
95	return unsafe.Pointer(n.data)
96}
97
98// DataRaw is a wrapper around the data struct field
99func (v *SList) DataRaw() unsafe.Pointer {
100	n := v.native()
101	if n == nil {
102		return nil
103	}
104	return unsafe.Pointer(n.data)
105}
106
107// Data acts the same as data struct field, but it returns raw unsafe.Pointer as interface.
108// TODO: Align with List struct and add member + logic for `dataWrap func(unsafe.Pointer) interface{}`?
109func (v *SList) Data() interface{} {
110	ptr := v.dataRaw()
111	if v.dataWrap != nil {
112		return v.dataWrap(ptr)
113	}
114	return ptr
115}
116
117// Foreach acts the same as g_slist_foreach().
118// No user_data argument is implemented because of Go clojure capabilities.
119func (v *SList) Foreach(fn func(item interface{})) {
120	for l := v; l != nil; l = l.Next() {
121		fn(l.Data())
122	}
123}
124
125// Free is a wrapper around g_slist_free().
126func (v *SList) Free() {
127	C.g_slist_free(v.native())
128}
129
130// FreeFull is a wrapper around g_slist_free_full().
131func (v *SList) FreeFull() {
132	//TODO implement GDestroyNotify callback
133	C.g_slist_free_full(v.native(), nil)
134}
135
136// GSList * 	g_slist_alloc ()
137// GSList * 	g_slist_prepend ()
138// GSList * 	g_slist_insert ()
139// GSList * 	g_slist_insert_before ()
140// GSList * 	g_slist_insert_sorted ()
141// GSList * 	g_slist_remove ()
142// GSList * 	g_slist_remove_link ()
143// GSList * 	g_slist_delete_link ()
144// GSList * 	g_slist_remove_all ()
145// void 	g_slist_free_1 ()
146// GSList * 	g_slist_copy ()
147// GSList * 	g_slist_copy_deep ()
148// GSList * 	g_slist_reverse ()
149// GSList * 	g_slist_insert_sorted_with_data ()
150// GSList * 	g_slist_sort ()
151// GSList * 	g_slist_sort_with_data ()
152// GSList * 	g_slist_concat ()
153// GSList * 	g_slist_last ()
154// GSList * 	g_slist_nth ()
155// gpointer 	g_slist_nth_data ()
156// GSList * 	g_slist_find ()
157// GSList * 	g_slist_find_custom ()
158// gint 	g_slist_position ()
159// gint 	g_slist_index ()
160