1// package types implements types as found in gir XML files
2// NOTE: This was copied largely from (the type definitions) from https://github.com/diamondburned/gotk4
3package types
4
5import (
6 "encoding/xml"
7 "fmt"
8 "strconv"
9 "strings"
10
11 "github.com/bnema/puregotk/internal/gir/util"
12)
13
14// convList maps the given GIR primitive type to a Go builtin type.
15// See https://github.com/diamondburned/gotk4/blob/fd960d20b525a07580938d10a214336bafb47d12/gir/girgen/types/types.go#LL483C1-L512C2
16var convList = map[string]string{
17 "none": "",
18 "gboolean": "bool",
19 "gfloat": "float32",
20 "gdouble": "float64",
21 "gint": "int",
22 "gssize": "int",
23 "gint8": "int8",
24 "gint16": "int16",
25 "gshort": "int16",
26 "gint32": "int32",
27 "glong": "int",
28 "int32": "int32",
29 "gint64": "int64",
30 "guint": "uint",
31 "gsize": "uint",
32 "guchar": "byte",
33 "gchar": "byte",
34 "guint8": "byte", // some weird cases
35 "guint16": "uint16",
36 "gushort": "uint16",
37 "guint32": "uint32",
38 "gulong": "uint",
39 "gunichar": "uint32",
40 "guint64": "uint64",
41 "guintptr": "uintptr",
42 "utf8": "string",
43 "filename": "string",
44 "GType": "types.GType",
45 "uid_t": "uint",
46 "pid_t": "int",
47 "time_t": "int",
48 "gintptr": "int",
49
50 // these are probably not correct but needed to compile
51 "_Value__data__union": "uint64",
52 "long double": "float64",
53 "va_list": "[]interface{}",
54 "gpointer": "uintptr",
55 "const char*": "string",
56 "const char**": "[]string",
57 "char**": "[]string",
58 // not exported
59 "HarfBuzz.feature_t": "uintptr",
60 "HarfBuzz.font_t": "uintptr",
61 //"GLib.Quark": "byte",
62 //"Allocation": "uintptr",
63}
64
65// Repository represents a GObject Introspection Repository, which contains the
66// includes, C includes and namespaces of a single gir file.
67type Repository struct {
68 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 repository"`
69
70 Version string `xml:"version,attr"`
71 CIdentifierPrefixes string `xml:"http://www.gtk.org/introspection/c/1.0 identifier-prefixes,attr"`
72 CSymbolPrefixes string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefixes,attr"`
73
74 Includes []Include `xml:"http://www.gtk.org/introspection/core/1.0 include"`
75 CIncludes []CInclude `xml:"http://www.gtk.org/introspection/c/1.0 include"`
76 Packages []Package `xml:"http://www.gtk.org/introspection/core/1.0 package"`
77 Namespaces []Namespace `xml:"http://www.gtk.org/introspection/core/1.0 namespace"`
78}
79
80// https://gitlab.gnome.org/GNOME/gobject-introspection/-/blob/master/docs/gir-1.2.rnc
81
82type Alias struct {
83 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 alias"`
84
85 Name string `xml:"name,attr"`
86 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
87
88 InfoAttrs
89 InfoElements
90
91 Type Type `xml:"http://www.gtk.org/introspection/core/1.0 type"`
92}
93
94func (a *Alias) Template(ns string, kinds KindMap) string {
95 if v, ok := convList[a.CType]; ok {
96 return util.NormalizeNamespace(ns, v, true)
97 }
98 return a.Type.Template(ns, kinds, false)
99}
100
101type AnyType struct {
102 // Possible variants.
103 Type *Type `xml:"http://www.gtk.org/introspection/core/1.0 type"`
104 Array *Array `xml:"http://www.gtk.org/introspection/core/1.0 array"`
105}
106
107func (a *AnyType) Translate(ns string, kinds KindMap) string {
108 if a == nil {
109 panic("unknown type found")
110 }
111 t := a.Type
112 if t == nil {
113 if a.Array == nil {
114 // no type information available
115 return ""
116 }
117 return a.Array.Template(ns, kinds)
118 }
119 return a.Type.Template(ns, kinds, false)
120}
121
122type Annotation struct {
123 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 attribute"`
124 Name string `xml:"name,attr"`
125 Value string `xml:"value,attr"`
126}
127
128type Array struct {
129 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 array"`
130 Name string `xml:"name,attr"`
131 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
132 Length *int `xml:"length,attr"` // ix of .Parameters
133 ZeroTerminated *bool `xml:"zero-terminated,attr"`
134 FixedSize int `xml:"fixed-size,attr"`
135 Introspectable bool `xml:"introspectable,attr"`
136 // Type is the array's inner type.
137 Type *Type `xml:"http://www.gtk.org/introspection/core/1.0 type"`
138}
139
140func (a *Array) Size() int {
141 // there is a Length property
142 // but it seems that GTK doesn't really use this
143 // see e.g. gtk_css_provider_load_from_data
144 //if a.Length != nil {
145 // return *a.Length
146 //}
147 return a.FixedSize
148}
149
150func ReplaceSize(str string, n int) string {
151 trimmed := strings.TrimPrefix(str, "*")
152 if trimmed == str {
153 trimmed = strings.TrimPrefix(str, "[]")
154 }
155 return fmt.Sprintf("[%d]%s", n, trimmed)
156}
157
158func (a *Array) Template(ns string, kinds KindMap) string {
159 // Does the c type exist in our little hacky conversion rule?
160 if v, ok := convList[a.CType]; ok {
161 return v
162 }
163 // default case of an array is just a pointer
164 ret := "uintptr"
165
166 if a.Type != nil {
167 t := a.Type.Template(ns, kinds, true)
168 if strings.Count(t, "*") > 0 {
169 return "uintptr"
170 }
171 ret = "[]" + t
172 }
173
174 // Check if there is a fixed size
175 n := a.Size()
176 if n > 0 {
177 return ReplaceSize(ret, n)
178 }
179 return ret
180}
181
182// IsZeroTerminated returns true if the Array is zero-terminated. It accounts
183// for edge cases of the structure.
184func (a Array) IsZeroTerminated() bool {
185 return a.Name == "" && (a.ZeroTerminated == nil || *a.ZeroTerminated)
186}
187
188type Bitfield struct {
189 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 bitfield"`
190
191 Name string `xml:"name,attr"` // Go case
192 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
193 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
194 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
195
196 Members []Member `xml:"http://www.gtk.org/introspection/core/1.0 member"`
197 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
198
199 InfoAttrs
200 InfoElements
201}
202
203func (b *Bitfield) Template(ns string) EnumTemplate {
204 els := make([]enumValues, len(b.Members))
205 for i, m := range b.Members {
206 v, err := strconv.Atoi(m.Value)
207 if err != nil {
208 panic(err)
209 }
210 // + Value needed to get rid of duplicates
211 els[i] = enumValues{
212 Doc: m.Doc.StringSafe(),
213 Name: util.SnakeToCamel(util.RemoveSnakePrefix(strings.ToLower(m.CIdentifier), ns)) + "Value",
214 Value: v,
215 }
216 }
217 return EnumTemplate{
218 Name: util.SnakeToCamel(b.Name),
219 Doc: b.Doc.StringSafe(),
220 Values: els,
221 TypeGetter: b.GLibGetType,
222 }
223}
224
225type Signal struct {
226 XMLName xml.Name `xml:"http://www.gtk.org/introspection/glib/1.0 signal"`
227 Name string `xml:"name,attr"`
228 Detailed bool `xml:"detailed,attr"`
229 When SignalWhen `xml:"when,attr"`
230 Action bool `xml:"action,attr"`
231 NoHooks bool `xml:"no-hooks,attr"`
232 NoRecurse bool `xml:"no-recurse,attr"`
233 InfoElements
234 Parameters *Parameters `xml:"http://www.gtk.org/introspection/core/1.0 parameters"`
235 ReturnValue *ReturnValue `xml:"http://www.gtk.org/introspection/core/1.0 return-value"`
236}
237
238type SignalWhen string
239
240const (
241 SignalWhenFirst = "first"
242 SignalWhenLast = "last"
243 SignalWhenCleanup = "cleanup"
244)
245
246type SourcePosition struct {
247 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 source-position"`
248 Filename string `xml:"filename,attr"`
249 Line int `xml:"line,attr"`
250 Column int `xml:"column,attr"`
251}
252
253type TransferOwnership struct {
254 TransferOwnership string `xml:"transfer-ownership,attr"`
255}
256
257type Type struct {
258 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 type"`
259
260 Name string `xml:"name,attr"`
261 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
262 Introspectable *bool `xml:"introspectable,attr"`
263
264 DocElements
265 // Types is the type's inner types.
266 Types []Type `xml:"http://www.gtk.org/introspection/core/1.0 type"`
267}
268
269func (typ *Type) IsIntrospectable() bool {
270 return typ.Introspectable == nil || *typ.Introspectable
271}
272
273func (t *Type) Template(ns string, kinds KindMap, array bool) string {
274 if v, ok := convList[t.Name]; ok {
275 return v
276 }
277
278 _type := util.NormalizeNamespace(ns, t.Name, true)
279
280 kind := kinds.Kind(ns, _type)
281 // find the total pointer count
282 count := strings.Count(t.CType, "*")
283 w := strings.Trim(t.CType, "*")
284 if w == "gpointer" {
285 count += 1
286 }
287 // set the same pointer types on the name
288 if count > 0 && kind != CallbackType {
289 _type = strings.Repeat("*", count) + _type
290 } else if kind == RecordsType {
291 if array {
292 return _type
293 }
294 // if it's not a pointer
295 // then purego doesn't support it (struct by value is not supported
296 // so return uintptr
297 _type = "uintptr"
298 }
299 return _type
300}
301
302type Union struct {
303 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 union"`
304
305 Name string `xml:"name,attr"` // Go case
306 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
307 CSymbolPrefix string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefix,attr"`
308 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
309 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
310
311 InfoAttrs
312 InfoElements
313
314 Fields []Field `xml:"http://www.gtk.org/introspection/core/1.0 field"`
315 Constructors []Constructor `xml:"http://www.gtk.org/introspection/core/1.0 constructor"`
316 Methods []Method `xml:"http://www.gtk.org/introspection/core/1.0 method"`
317 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
318 Records []Record `xml:"http://www.gtk.org/introspection/core/1.0 record"`
319}
320
321type VarArgs struct {
322 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 varargs"`
323}
324
325type VirtualMethod struct {
326 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 virtual-method"`
327
328 Invoker string `xml:"invoker,attr"`
329 CallableAttrs
330}
331
332type Boxed struct{}
333
334type CInclude struct {
335 XMLName xml.Name `xml:"http://www.gtk.org/introspection/c/1.0 include"`
336 Name string `xml:"name,attr"`
337}
338
339type CallableAttrs struct {
340 Name string `xml:"name,attr"`
341 CIdentifier string `xml:"http://www.gtk.org/introspection/c/1.0 identifier,attr"`
342 ShadowedBy string `xml:"shadowed-by,attr"`
343 Shadows string `xml:"shadows,attr"`
344 Throws bool `xml:"throws,attr"`
345 MovedTo string `xml:"moved-to,attr"`
346 Parameters *Parameters `xml:"http://www.gtk.org/introspection/core/1.0 parameters"`
347 ReturnValue *ReturnValue `xml:"http://www.gtk.org/introspection/core/1.0 return-value"`
348 InfoAttrs
349 InfoElements
350}
351
352type Callback struct {
353 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 callback"`
354 CallableAttrs
355}
356
357type Class struct {
358 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 class"`
359 Name string `xml:"name,attr"`
360 Parent string `xml:"parent,attr"`
361 Abstract bool `xml:"abstract,attr"`
362
363 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
364 CSymbolPrefix string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefix,attr"`
365
366 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
367 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
368 GLibTypeStruct string `xml:"http://www.gtk.org/introspection/glib/1.0 type-struct,attr"`
369
370 InfoAttrs
371 InfoElements
372
373 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
374 Implements []Implements `xml:"http://www.gtk.org/introspection/core/1.0 implements"`
375 Constructors []Constructor `xml:"http://www.gtk.org/introspection/core/1.0 constructor"`
376 Methods []Method `xml:"http://www.gtk.org/introspection/core/1.0 method"`
377 VirtualMethods []VirtualMethod `xml:"http://www.gtk.org/introspection/core/1.0 virtual-method"`
378 Fields []Field `xml:"http://www.gtk.org/introspection/core/1.0 field"`
379 Properties []Property `xml:"http://www.gtk.org/introspection/core/1.0 property"`
380 Signals []Signal `xml:"http://www.gtk.org/introspection/glib/1.0 signal"`
381}
382
383type Constant struct {
384 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 constant"`
385 Name string `xml:"name,attr"`
386 Value string `xml:"value,attr"`
387 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
388
389 Type Type `xml:"http://www.gtk.org/introspection/core/1.0 type"`
390
391 InfoAttrs
392 InfoElements
393}
394
395func (c *Constant) Template(ns string, kinds KindMap) ConstantTemplate {
396 t := c.Type.Template(ns, kinds, false)
397 v := c.Value
398
399 switch t {
400 case "string":
401 v = fmt.Sprintf(`"%s"`, v)
402 }
403
404 return ConstantTemplate{
405 Name: c.Name,
406 Doc: c.Doc.StringSafe(),
407 Type: t,
408 Value: v,
409 }
410}
411
412type Constructor struct {
413 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 constructor"`
414 CallableAttrs
415}
416
417type Doc struct {
418 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 doc"`
419 Filename string `xml:"filename,attr"`
420 String string `xml:",innerxml"`
421 Line int `xml:"line,attr"`
422}
423
424func (d *Doc) StringSafe() string {
425 if d == nil {
426 return ""
427 }
428 lines := strings.Split(d.String, "\n")
429 for i, l := range lines {
430 lines[i] = "// " + l
431 }
432 return strings.Join(lines, "\n")
433}
434
435type DocDeprecated struct {
436 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 doc-deprecated"`
437 String string `xml:",innerxml"`
438}
439
440type DocElements struct {
441 Doc *Doc
442 DocDeprecated *DocDeprecated
443 SourcePosition *SourcePosition
444}
445
446func (d *DocElements) FilenameSafe() string {
447 if d == nil || (d.SourcePosition == nil && d.Doc == nil) {
448 return "main.go"
449 }
450 if d.SourcePosition != nil {
451 return util.TranslateFilename(d.SourcePosition.Filename)
452 }
453 return util.TranslateFilename(d.Doc.Filename)
454}
455
456type Enum struct {
457 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 enumeration"`
458
459 Name string `xml:"name,attr"` // Go case
460 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
461 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
462 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
463 GLibErrorDomain string `xml:"http://www.gtk.org/introspection/glib/1.0 error-domain,attr"`
464
465 Members []Member `xml:"http://www.gtk.org/introspection/core/1.0 member"`
466 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
467
468 InfoAttrs
469 InfoElements
470}
471
472func (e *Enum) Template(ns string) EnumTemplate {
473 els := make([]enumValues, len(e.Members))
474
475 for i, m := range e.Members {
476 v, err := strconv.Atoi(m.Value)
477 if err != nil {
478 panic(err)
479 }
480 id := strings.ToLower(m.CIdentifier)
481 sID := util.RemoveSnakePrefix(id, ns)
482 els[i] = enumValues{
483 Doc: m.Doc.StringSafe(),
484 // + Value needed to get rid of duplicates
485 Name: util.SnakeToCamel(sID) + "Value",
486 Value: v,
487 }
488 }
489 return EnumTemplate{
490 Name: util.SnakeToCamel(e.Name),
491 Doc: e.Doc.StringSafe(),
492 Values: els,
493 TypeGetter: e.GLibGetType,
494 }
495}
496
497type Field struct {
498 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 field"`
499 Name string `xml:"name,attr"`
500 Bits int `xml:"bits,attr"`
501 Private bool `xml:"private,attr"`
502 Writable bool `xml:"writable,attr"` // default false
503 Readable *bool `xml:"readable,attr"` // default true
504 AnyType
505 Callback *Callback
506 Doc *Doc
507}
508
509// IsReadable returns true if the field is readable.
510func (f Field) IsReadable() bool {
511 return f.Readable == nil || *f.Readable
512}
513
514type Function struct {
515 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 function"`
516 CallableAttrs
517}
518
519type Implements struct {
520 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 implements"`
521 Name string `xml:"name,attr"`
522}
523
524type Include struct {
525 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 include"`
526 Name string `xml:"name,attr"`
527 Version string `xml:"version,attr"`
528}
529
530type InfoAttrs struct {
531 Introspectable *bool `xml:"introspectable,attr"` // default true
532 Deprecated bool `xml:"deprecated,attr"`
533 DeprecatedVersion string `xml:"deprecated-version,attr"`
534 Version string `xml:"version,attr"`
535 Stability string `xml:"stability,attr"`
536}
537
538// IsIntrospectable returns true if the InfoAttrs indicates that the type is
539// introspectable.
540func (inf InfoAttrs) IsIntrospectable() bool {
541 return inf.Introspectable == nil || *inf.Introspectable
542}
543
544type InfoElements struct {
545 DocElements
546 Annotations []Annotation `xml:"http://www.gtk.org/introspection/core/1.0 attribute"`
547}
548
549type InstanceParameter struct {
550 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 instance-parameter"`
551 ParameterAttrs
552}
553
554type Interface struct {
555 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 interface"`
556 Name string `xml:"name,attr"`
557
558 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
559 CSymbolPrefix string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefix,attr"`
560
561 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
562 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
563 GLibTypeStruct string `xml:"http://www.gtk.org/introspection/glib/1.0 type-struct,attr"`
564
565 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
566 Methods []Method `xml:"http://www.gtk.org/introspection/core/1.0 method"`
567 VirtualMethods []VirtualMethod `xml:"http://www.gtk.org/introspection/core/1.0 virtual-method"`
568 Prerequisites []Prerequisite `xml:"http://www.gtk.org/introspection/core/1.0 prerequisite"`
569 Properties []Property `xml:"http://www.gtk.org/introspection/core/1.0 property"`
570 Signals []Signal `xml:"http://www.gtk.org/introspection/glib/1.0 signal"`
571
572 InfoAttrs
573 InfoElements
574}
575
576type Member struct {
577 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 member"`
578
579 Names []xml.Attr `xml:"name,attr"`
580 Value string `xml:"value,attr"`
581 CIdentifier string `xml:"http://www.gtk.org/introspection/c/1.0 identifier,attr"`
582 GLibNick string `xml:"http://www.gtk.org/introspection/glib/1.0 nick,attr"`
583
584 InfoAttrs
585 InfoElements
586}
587
588func (m Member) Name() string {
589 return m.nameAttr(xml.Name{Local: "name"})
590}
591
592func (m Member) GLibName() string {
593 return m.nameAttr(xml.Name{Space: "http://www.gtk.org/introspection/glib/1.0", Local: "name"})
594}
595
596func (m Member) nameAttr(name xml.Name) string {
597 for _, attr := range m.Names {
598 if attr.Name == name {
599 return attr.Value
600 }
601 }
602 return ""
603}
604
605type Method struct {
606 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 method"`
607 CallableAttrs
608}
609
610type Namespace struct {
611 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 namespace"`
612
613 Name string `xml:"name,attr"`
614 Version string `xml:"version,attr"`
615 CIdentifierPrefixes string `xml:"http://www.gtk.org/introspection/c/1.0 identifier-prefixes,attr"`
616 CSymbolPrefixes string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefixes,attr"`
617 Prefix string `xml:"http://www.gtk.org/introspection/c/1.0 prefix,attr"`
618 SharedLibrary string `xml:"shared-library,attr"`
619
620 Aliases []Alias `xml:"http://www.gtk.org/introspection/core/1.0 alias"`
621 Classes []Class `xml:"http://www.gtk.org/introspection/core/1.0 class"`
622 Interfaces []Interface `xml:"http://www.gtk.org/introspection/core/1.0 interface"`
623 Records []Record `xml:"http://www.gtk.org/introspection/core/1.0 record"`
624 Enums []Enum `xml:"http://www.gtk.org/introspection/core/1.0 enumeration"`
625 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
626 Unions []Union `xml:"http://www.gtk.org/introspection/core/1.0 union"`
627 Bitfields []Bitfield `xml:"http://www.gtk.org/introspection/core/1.0 bitfield"`
628 Callbacks []Callback `xml:"http://www.gtk.org/introspection/core/1.0 callback"`
629 Constants []Constant `xml:"http://www.gtk.org/introspection/core/1.0 constant"`
630 Annotations []Annotation `xml:"http://www.gtk.org/introspection/core/1.0 attribute"`
631 Boxeds []Boxed `xml:"http://www.gtk.org/introspection/core/1.0 boxed"`
632}
633
634type Package struct {
635 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 package"`
636 Name string `xml:"name,attr"`
637}
638
639type Parameter struct {
640 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 parameter"`
641 ParameterAttrs
642}
643
644func (p *Parameter) Translate(ns string, kinds KindMap) string {
645 if p.Name == "..." {
646 return "...interface{}"
647 }
648 return p.AnyType.Translate(ns, kinds)
649}
650
651func (p *Parameter) VarName() string {
652 snaked := util.SnakeToCamel(p.Name)
653 if snaked == "..." {
654 return "varArgs"
655 }
656 // avoid clash between same name of type and var
657 // could also do first letter to lower?
658 return snaked + "Var"
659}
660
661func (p *Parameters) Template(ns string, ifacens string, kinds KindMap, throws bool, ctx ArgContext) funcArgsTemplate {
662 if p == nil {
663 return funcArgsTemplate{}
664 }
665 params := p.Parameters
666 if len(params) == 0 {
667 return funcArgsTemplate{}
668 }
669 args := funcArgsTemplate{}
670 for _, par := range params {
671 args.Add(par, ifacens, ns, kinds, ctx)
672 }
673 if throws {
674 args.AddThrows(ns)
675 }
676 return args
677}
678
679type ParameterAttrs struct {
680 Name string `xml:"name,attr"`
681 Direction string `xml:"direction,attr"`
682 Scope string `xml:"scope,attr"`
683 Closure *int `xml:"closure,attr"`
684 Destroy *int `xml:"destroy,attr"`
685 CallerAllocates bool `xml:"caller-allocates,attr"`
686 Skip bool `xml:"skip,attr"`
687 Optional bool `xml:"optional,attr"`
688 Nullable bool `xml:"nullable,attr"`
689
690 TransferOwnership
691 AnyType
692 Doc *Doc
693}
694
695type Parameters struct {
696 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 parameters"`
697 InstanceParameter *InstanceParameter `xml:"http://www.gtk.org/introspection/core/1.0 instance-parameter"`
698 Parameters []Parameter `xml:"http://www.gtk.org/introspection/core/1.0 parameter"`
699}
700
701type Prerequisite struct {
702 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 prerequisite"`
703 Name string `xml:"name,attr"`
704}
705
706type Property struct {
707 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 property"`
708 Name string `xml:"name,attr"`
709 Writable bool `xml:"writable,attr"`
710 Readable *bool `xml:"readable,attr"` // default true
711 Construct bool `xml:"construct,attr"`
712 ConstructOnly bool `xml:"construct-only,attr"`
713 DefaultValue string `xml:"default-value,attr"`
714 Getter string `xml:"getter,attr"`
715 Setter string `xml:"setter,attr"`
716 TransferOwnership string `xml:"transfer-ownership,attr"`
717
718 AnyType
719 InfoElements
720}
721
722func (p Property) IsReadable() bool {
723 return p.Readable == nil || *p.Readable
724}
725
726func (p *Property) Template(ns string, kinds KindMap) PropertyTemplate {
727 var (
728 goType = p.AnyType.Translate(ns, kinds)
729 cName = p.Name
730 gvalueType, setMethod, getMethod = mapGoTypeToGValue(goType)
731 )
732
733 return PropertyTemplate{
734 Doc: p.Doc.StringSafe(),
735 Name: util.DashToCamel(cName),
736 CName: cName,
737 GoType: goType,
738 GValueType: gvalueType,
739 SetMethod: setMethod,
740 GetMethod: getMethod,
741 Readable: p.IsReadable(),
742 Writable: p.Writable,
743 }
744}
745
746func mapGoTypeToGValue(goType string) (gvalueType, setMethod, getMethod string) {
747 switch strings.TrimPrefix(goType, "*") {
748 case "bool":
749 return "TypeBooleanVal", "SetBoolean", "GetBoolean"
750 case "byte":
751 return "TypeUcharVal", "SetUchar", "GetUchar"
752 case "int8":
753 return "TypeCharVal", "SetSchar", "GetSchar"
754 case "int":
755 return "TypeIntVal", "SetInt", "GetInt"
756 case "uint":
757 return "TypeUintVal", "SetUint", "GetUint"
758 case "int32":
759 return "TypeLongVal", "SetLong", "GetLong"
760 case "uint32":
761 return "TypeUlongVal", "SetUlong", "GetUlong"
762 case "int64":
763 return "TypeInt64Val", "SetInt64", "GetInt64"
764 case "uint64":
765 return "TypeUint64Val", "SetUint64", "GetUint64"
766 case "float32":
767 return "TypeFloatVal", "SetFloat", "GetFloat"
768 case "float64":
769 return "TypeDoubleVal", "SetDouble", "GetDouble"
770 case "string":
771 return "TypeStringVal", "SetString", "GetString"
772 case "uintptr":
773 return "TypePointerVal", "SetPointer", "GetPointer"
774 case "[]string":
775 return "BoxedStrv", "SetBoxed", "GetBoxed"
776 case "[]byte":
777 return "BoxedByteArray", "SetBoxed", "GetBoxed"
778 case "[]uintptr":
779 return "BoxedPtrArray", "SetBoxed", "GetBoxed"
780 default:
781 return "", "", ""
782 }
783}
784
785type Record struct {
786 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 record"`
787 Name string `xml:"name,attr"`
788 CType string `xml:"http://www.gtk.org/introspection/c/1.0 type,attr"`
789 GLibTypeName string `xml:"http://www.gtk.org/introspection/glib/1.0 type-name,attr"`
790 GLibGetType string `xml:"http://www.gtk.org/introspection/glib/1.0 get-type,attr"`
791 CSymbolPrefix string `xml:"http://www.gtk.org/introspection/c/1.0 symbol-prefix,attr"`
792 GLibIsGTypeStructFor string `xml:"http://www.gtk.org/introspection/glib/1.0 is-gtype-struct-for,attr"`
793 Disguised bool `xml:"disguised,attr"`
794 Foreign bool `xml:"foreign,attr"`
795
796 Fields []Field `xml:"http://www.gtk.org/introspection/core/1.0 field"`
797 Functions []Function `xml:"http://www.gtk.org/introspection/core/1.0 function"`
798 Unions []Union `xml:"http://www.gtk.org/introspection/core/1.0 union"`
799 Methods []Method `xml:"http://www.gtk.org/introspection/core/1.0 method"`
800 Constructors []Constructor `xml:"http://www.gtk.org/introspection/core/1.0 constructor"`
801 Properties []Property `xml:"http://www.gtk.org/introspection/core/1.0 property"`
802
803 InfoAttrs
804 InfoElements
805}
806
807type ReturnValue struct {
808 XMLName xml.Name `xml:"http://www.gtk.org/introspection/core/1.0 return-value"`
809 Scope string `xml:"scope,attr"`
810 Closure *int `xml:"closure,attr"`
811 Destroy *int `xml:"destroy,attr"`
812 Introspectable bool `xml:"introspectable,attr"`
813 Nullable bool `xml:"nullable,attr"`
814 Skip bool `xml:"skip,attr"`
815 AllowNone bool `xml:"allow-none,attr"`
816 TransferOwnership
817 DocElements
818 AnyType
819}
820
821func (r *ReturnValue) Template(ns string, ins string, kinds KindMap, throws bool) funcRetTemplate {
822 val := r.AnyType.Translate(ns, kinds)
823 raw := val
824 class := false
825 lns := ns
826 if ins != "" {
827 lns = ins
828 }
829 kind := kinds.Kind(lns, raw)
830 stars := strings.Count(val, "*")
831
832 if kind != OtherType && kind != UnknownType && kind != SliceType {
833 val = util.AddNamespace(val, ins)
834 }
835 if stars > 0 {
836 val = util.StarsInFront(strings.ReplaceAll(val, "*", ""), stars)
837 }
838 switch kind {
839 case ClassesType:
840 raw = "uintptr"
841 class = true
842 // TODO: why does this happen?
843 if strings.HasPrefix(val, "[]") {
844 class = false
845 val = "uintptr"
846 }
847 case InterfacesType:
848 raw = "uintptr"
849 val += "Base"
850 class = true
851 // callback returns should always be uintptr
852 // I needed this for glib.LogSetDefaultHandler
853 // Otherwise I got 'panic: reflect.MakeFunc: value of type *glib.LogFunc is not assignable to type glib.LogFunc'
854 case CallbackType:
855 raw = "uintptr"
856 val = "uintptr"
857 case SliceType:
858 // our purego fork supports string slices as return values
859 if val != "[]string" {
860 raw = "uintptr"
861 val = "uintptr"
862 }
863 }
864 return funcRetTemplate{
865 Raw: raw,
866 Value: val,
867 Class: class,
868 RefSink: r.TransferOwnership.TransferOwnership == "none",
869 Throws: throws,
870 }
871}