From 3b5e0297cbf6f35f4740d614b3606c5bfa6bbb19 Mon Sep 17 00:00:00 2001 From: x1unix Date: Sat, 25 Apr 2020 19:14:12 +0300 Subject: [PATCH] gio: add core GResource implementation --- gio/gresource.go | 102 +++++++++++++++++++++++++++++++++++++++++++++ gio/gresource.go.h | 13 ++++++ gio/utils.go | 23 ++++++++++ 3 files changed, 138 insertions(+) create mode 100644 gio/gresource.go create mode 100644 gio/gresource.go.h create mode 100644 gio/utils.go diff --git a/gio/gresource.go b/gio/gresource.go new file mode 100644 index 00000000..ae39464d --- /dev/null +++ b/gio/gresource.go @@ -0,0 +1,102 @@ +// package resource wraps operations over GResource +package gio + +// #cgo pkg-config: gio-2.0 glib-2.0 gobject-2.0 +// #include +// #include +// #include "gresource.go.h" +import "C" +import ( + "errors" + "unsafe" +) + +// ResourceLookupFlags is a representation of GTK's GResourceLookupFlags +type ResourceLookupFlags int + +func (f ResourceLookupFlags) native() C.GResourceLookupFlags { + return (C.GResourceLookupFlags)(f) +} + +const ( + G_RESOURCE_LOOKUP_FLAGS_NONE ResourceLookupFlags = C.G_RESOURCE_LOOKUP_FLAGS_NONE +) + +// GResource wraps native GResource object +// +// See: https://developer.gnome.org/gio/stable/GResource.html +type GResource *C.GResource + +// LoadGResource is a wrapper around g_resource_load() +// +// See: https://developer.gnome.org/gio/stable/GResource.html#g-resource-load +func LoadGResource(path string) (GResource, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + var gerr *C.GError + + resPtr := C.g_resource_load((*C.gchar)(unsafe.Pointer(cpath)), &gerr) + if gerr != nil { + defer C.g_error_free(gerr) + return nil, errors.New(goString(gerr.message)) + } + + res := wrapGResource(resPtr) + return res, nil +} + +// NewGResourceFromData is a wrapper around g_resource_new_from_data() +// +// See: https://developer.gnome.org/gio/stable/GResource.html#g-resource-new-from-data +func NewGResourceFromData(data []byte) (GResource, error) { + arrayPtr := (*C.GBytes)(unsafe.Pointer(&data[0])) + var gerr *C.GError + resPtr := C.g_resource_new_from_data(arrayPtr, &gerr) + if gerr != nil { + defer C.g_error_free(gerr) + return nil, errors.New(goString(gerr.message)) + } + + res := wrapGResource(resPtr) + return res, nil +} + +// Register wraps g_resources_register() +// +// See: https://developer.gnome.org/gio/stable/GResource.html#g-resources-register +func RegisterGResource(res GResource) { + C.g_resources_register(res) +} + +// Unregister wraps g_resources_unregister() +// +// See: https://developer.gnome.org/gio/stable/GResource.html#g-resources-unregister +func UnregisterGResource(res GResource) { + C.g_resources_unregister(res) +} + +// GResourceEnumerateChildren wraps g_resources_enumerate_children() +// +// See: https://developer.gnome.org/gio/stable/GResource.html#g-resources-enumerate-children +func GResourceEnumerateChildren(path string, flags ResourceLookupFlags) ([]string, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + var gerr *C.GError + arrChildren := C.g_resources_enumerate_children(cpath, flags.native(), &gerr) + if gerr != nil { + defer C.g_error_free(gerr) + return nil, errors.New(goString(gerr.message)) + } + + if arrChildren == nil { + return nil, errors.New("unexpected nil pointer from g_resources_enumerate_children") + } + + arr := toGoStringArray(arrChildren) + return arr, nil +} + +func wrapGResource(resPtr *C.GResource) GResource { + res := GResource(resPtr) + return res +} diff --git a/gio/gresource.go.h b/gio/gresource.go.h new file mode 100644 index 00000000..6ff914e6 --- /dev/null +++ b/gio/gresource.go.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include +#include +#include + +static inline char** next_charptr(char** s) { return (s+1); } + +static inline void char_g_strfreev(char** s) { + g_strfreev((gchar**) s); +} diff --git a/gio/utils.go b/gio/utils.go new file mode 100644 index 00000000..fe5b26e1 --- /dev/null +++ b/gio/utils.go @@ -0,0 +1,23 @@ +package gio + +// #include +// #include "gresource.go.h" +import "C" + +// same implementation as package glib +func toGoStringArray(c **C.char) []string { + var strs []string + originalc := c + defer C.char_g_strfreev(originalc) + + for *c != nil { + strs = append(strs, C.GoString((*C.char)(*c))) + c = C.next_charptr(c) + } + + return strs +} + +func goString(cstr *C.gchar) string { + return C.GoString((*C.char)(cstr)) +}